diff --git a/src/sgw/sgw_context.c b/src/sgw/sgw_context.c index 72d1127fef..2e44036bd9 100644 --- a/src/sgw/sgw_context.c +++ b/src/sgw/sgw_context.c @@ -8,7 +8,6 @@ #include "types.h" #include "gtp_types.h" -#include "gtp_path.h" #include "context.h" #include "sgw_context.h" @@ -615,11 +614,12 @@ sgw_sess_t *sgw_sess_add( /* Set APN */ core_cpystrn(sess->pdn.apn, apn, MAX_APN_LEN+1); - list_init(&sess->bearer_list); list_append(&sgw_ue->sess_list, sess); sess->sgw_ue = sgw_ue; + list_init(&sess->bearer_list); + bearer = sgw_bearer_add(sess); d_assert(bearer, sgw_sess_remove(sess); return NULL, "Can't add default bearer context"); @@ -716,17 +716,17 @@ sgw_bearer_t* sgw_bearer_add(sgw_sess_t *sess) index_alloc(&sgw_bearer_pool, &bearer); d_assert(bearer, return NULL, "Bearer context allocation failed"); - tunnel = sgw_tunnel_add(bearer, GTP_F_TEID_S1_U_ENODEB_GTP_U); - d_assert(tunnel, return NULL, "Tunnel context allocation failed"); - - bearer->sgw_s1u_teid = bearer->index; - bearer->sgw_s1u_addr = sgw_self()->s1u_addr; bearer->sgw_s5u_teid = bearer->index; bearer->sgw_s5u_addr = sgw_self()->s5u_addr; bearer->sess = sess; list_append(&sess->bearer_list, bearer); + list_init(&bearer->tunnel_list); + + tunnel = sgw_tunnel_add(bearer, GTP_F_TEID_S1_U_ENODEB_GTP_U); + d_assert(tunnel, return NULL, "Tunnel context allocation failed"); + return bearer; } @@ -781,11 +781,6 @@ sgw_bearer_t* sgw_bearer_find_by_sgw_s5u_teid(c_uint32_t sgw_s5u_teid) return sgw_bearer_find(sgw_s5u_teid); } -sgw_bearer_t* sgw_bearer_find_by_sgw_s1u_teid(c_uint32_t sgw_s1u_teid) -{ - return sgw_bearer_find(sgw_s1u_teid); -} - sgw_bearer_t* sgw_bearer_find_by_sess_ebi(sgw_sess_t *sess, c_uint8_t ebi) { sgw_bearer_t *bearer = NULL; @@ -850,8 +845,9 @@ sgw_tunnel_t* sgw_tunnel_add(sgw_bearer_t *bearer, c_uint8_t interface_type) tunnel->interface_type = interface_type; tunnel->local_teid = tunnel->index; tunnel->local_addr = sgw_self()->s1u_addr; - + tunnel->bearer = bearer; + list_append(&bearer->tunnel_list, tunnel); return tunnel; @@ -874,10 +870,10 @@ status_t sgw_tunnel_remove_all(sgw_bearer_t *bearer) d_assert(bearer, return CORE_ERROR, "Null param"); - tunnel = list_first(&bearer->tunnel_list); + tunnel = sgw_tunnel_first(bearer); while (tunnel) { - next_tunnel = list_next(tunnel); + next_tunnel = sgw_tunnel_next(tunnel); sgw_tunnel_remove(tunnel); @@ -889,7 +885,7 @@ status_t sgw_tunnel_remove_all(sgw_bearer_t *bearer) sgw_tunnel_t* sgw_tunnel_find(index_t index) { - d_assert(index && index < MAX_POOL_OF_BEARER, return NULL, + d_assert(index && index < MAX_POOL_OF_TUNNEL, return NULL, "Invalid Index(%d)",index); return index_find(&sgw_tunnel_pool, index); @@ -900,6 +896,64 @@ sgw_tunnel_t* sgw_tunnel_find_by_teid(c_uint32_t teid) return sgw_tunnel_find(teid); } +sgw_tunnel_t* sgw_direct_tunnel_in_bearer(sgw_bearer_t *bearer) +{ + sgw_tunnel_t *tunnel = NULL; + + d_assert(bearer, return NULL,); + + tunnel = sgw_tunnel_first(bearer); + while(tunnel) + { + if (tunnel->interface_type == GTP_F_TEID_S1_U_ENODEB_GTP_U) + { + return tunnel; + } + + tunnel = sgw_tunnel_next(tunnel); + } + + return NULL; +} + +sgw_tunnel_t* sgw_dl_indirect_tunnel_in_bearer(sgw_bearer_t *bearer) +{ + sgw_tunnel_t *tunnel = NULL; + + d_assert(bearer, return NULL, "Null param"); + + tunnel = sgw_tunnel_first(bearer); + while (tunnel) + { + if (tunnel->interface_type == + GTP_F_TEID_ENODEB_GTP_U_FOR_DL_DATA_FORWARDING) + return tunnel; + + tunnel = sgw_tunnel_next(tunnel); + } + + return NULL; +} + +sgw_tunnel_t* sgw_ul_indirect_tunnel_in_bearer(sgw_bearer_t *bearer) +{ + sgw_tunnel_t *tunnel = NULL; + + d_assert(bearer, return NULL, "Null param"); + + tunnel = sgw_tunnel_first(bearer); + while (tunnel) + { + if (tunnel->interface_type == + GTP_F_TEID_ENODEB_GTP_U_FOR_UL_DATA_FORWARDING) + return tunnel; + + tunnel = sgw_tunnel_next(tunnel); + } + + return NULL; +} + sgw_tunnel_t* sgw_tunnel_first(sgw_bearer_t *bearer) { d_assert(bearer, return NULL, "Null param"); diff --git a/src/sgw/sgw_context.h b/src/sgw/sgw_context.h index 13f0631cc5..9123648093 100644 --- a/src/sgw/sgw_context.h +++ b/src/sgw/sgw_context.h @@ -116,19 +116,12 @@ typedef struct _sgw_bearer_t { c_uint8_t ebi; - /* IMPORTANT! - * SGW-S1U-TEID is same with an index */ - c_uint32_t sgw_s1u_teid; - c_uint32_t sgw_s1u_addr; - c_uint32_t enb_s1u_teid; - c_uint32_t enb_s1u_addr; - /* IMPORTANT! * SGW-S5U-TEID is same with an index */ c_uint32_t sgw_s5u_teid; c_uint32_t sgw_s5u_addr; - c_uint32_t pgw_s5u_teid; - c_uint32_t pgw_s5u_addr; + c_uint32_t enb_s1u_teid; + c_uint32_t enb_s1u_addr; /* User-Lication-Info */ tai_t tai; @@ -144,6 +137,7 @@ typedef struct _sgw_bearer_t { } sgw_bearer_t; typedef struct _sgw_tunnel_t { + lnode_t node; /**< A node of list_t */ index_t index; c_uint8_t interface_type; @@ -213,8 +207,6 @@ CORE_DECLARE(status_t) sgw_bearer_remove_all(sgw_sess_t *sess); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find(index_t index); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_sgw_s5u_teid( c_uint32_t sgw_s5u_teid); -CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_sgw_s1u_teid( - c_uint32_t sgw_s1u_teid); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_sess_ebi( sgw_sess_t *sess, c_uint8_t ebi); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_ue_ebi( @@ -230,6 +222,11 @@ CORE_DECLARE(status_t) sgw_tunnel_remove(sgw_tunnel_t *tunnel); CORE_DECLARE(status_t) sgw_tunnel_remove_all(sgw_bearer_t *bearer); CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_find(index_t index); CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_find_by_teid(c_uint32_t teid); +CORE_DECLARE(sgw_tunnel_t*) sgw_direct_tunnel_in_bearer(sgw_bearer_t *bearer); +CORE_DECLARE(sgw_tunnel_t*) sgw_dl_indirect_tunnel_in_bearer( + sgw_bearer_t *bearer); +CORE_DECLARE(sgw_tunnel_t*) sgw_ul_indirect_tunnel_in_bearer( + sgw_bearer_t *bearer); CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_first(sgw_bearer_t *bearer); CORE_DECLARE(sgw_tunnel_t*) sgw_tunnel_next(sgw_tunnel_t *tunnel); diff --git a/src/sgw/sgw_gtp_path.c b/src/sgw/sgw_gtp_path.c index 257d97d365..b758eab730 100644 --- a/src/sgw/sgw_gtp_path.c +++ b/src/sgw/sgw_gtp_path.c @@ -4,6 +4,7 @@ #include "core_net.h" #include "types.h" +#include "gtp_types.h" #include "gtp_path.h" #include "sgw_context.h" @@ -221,7 +222,7 @@ 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_bearer_t *bearer = NULL; + sgw_tunnel_t *tunnel = NULL; c_uint32_t teid; d_assert(sock, return -1, "Null param"); @@ -263,6 +264,28 @@ static int _gtpv1_s1u_recv_cb(net_sock_t *sock, void *data) 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_ENODEB_GTP_U) + gnode.sock = sgw_self()->s5u_sock; + else if (tunnel->interface_type == + GTP_F_TEID_ENODEB_GTP_U_FOR_DL_DATA_FORWARDING) + gnode.sock = sgw_self()->s1u_sock; + else if (tunnel->interface_type == + GTP_F_TEID_ENODEB_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); + } +#if 0 bearer = sgw_bearer_find_by_sgw_s1u_teid(teid); if (bearer) { @@ -275,6 +298,7 @@ static int _gtpv1_s1u_recv_cb(net_sock_t *sock, void *data) gtp_send(&gnode, pkbuf); } +#endif } pkbuf_free(pkbuf); diff --git a/src/sgw/sgw_s11_handler.c b/src/sgw/sgw_s11_handler.c index 63f2c9e99b..31b7e9e812 100644 --- a/src/sgw/sgw_s11_handler.c +++ b/src/sgw/sgw_s11_handler.c @@ -295,6 +295,7 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact, gtp_xact_t *s5c_xact = NULL; sgw_sess_t *sess = NULL; sgw_bearer_t *bearer = NULL; + sgw_tunnel_t *tunnel = NULL; gtp_create_bearer_response_t *req = NULL; gtp_f_teid_t *sgw_s1u_teid = NULL, *enb_s1u_teid = NULL; @@ -341,8 +342,10 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact, d_assert(sgw_s1u_teid, return, "Null param"); req->bearer_contexts.s4_u_sgsn_f_teid.presence = 0; - /* Find the Bearer by SGW-S1U-TEID */ - bearer = sgw_bearer_find_by_sgw_s1u_teid(ntohl(sgw_s1u_teid->teid)); + /* Find the Tunnel by SGW-S1U-TEID */ + tunnel = sgw_tunnel_find_by_teid(ntohl(sgw_s1u_teid->teid)); + d_assert(tunnel, return, "Null param"); + bearer = tunnel->bearer; d_assert(bearer, return, "Null param"); sess = bearer->sess; d_assert(sess, return, "Null param"); @@ -377,8 +380,8 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact, /* Data Plane(DL) : PGW-S5U */ memset(&pgw_s5u_teid, 0, sizeof(gtp_f_teid_t)); - pgw_s5u_teid.teid = htonl(bearer->pgw_s5u_teid); - pgw_s5u_teid.ipv4_addr = bearer->pgw_s5u_addr; + pgw_s5u_teid.teid = htonl(tunnel->remote_teid); + pgw_s5u_teid.ipv4_addr = tunnel->remote_addr; pgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_U; req->bearer_contexts.s5_s8_u_pgw_f_teid.presence = 1; req->bearer_contexts.s5_s8_u_pgw_f_teid.data = &pgw_s5u_teid; diff --git a/src/sgw/sgw_s5c_handler.c b/src/sgw/sgw_s5c_handler.c index db875419a0..b0fa0a7b4c 100644 --- a/src/sgw/sgw_s5c_handler.c +++ b/src/sgw/sgw_s5c_handler.c @@ -16,6 +16,7 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact, status_t rv; gtp_xact_t *s11_xact = NULL; sgw_bearer_t *bearer = NULL; + sgw_tunnel_t *tunnel = NULL; gtp_create_session_response_t *rsp = NULL; pkbuf_t *pkbuf = NULL; sgw_ue_t *sgw_ue = NULL; @@ -60,6 +61,8 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact, bearer = sgw_bearer_find_by_sess_ebi(sess, rsp->bearer_contexts_created.eps_bearer_id.u8); d_assert(bearer, return, "No Bearer Context"); + tunnel = sgw_direct_tunnel_in_bearer(bearer); + d_assert(tunnel, return, "No Tunnel Context"); /* Receive Control Plane(UL) : PGW-S5C */ pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. @@ -73,8 +76,8 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact, /* Receive Data Plane(UL) : PGW-S5U */ pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data; d_assert(pgw_s5u_teid, return, "Null param"); - bearer->pgw_s5u_teid = ntohl(pgw_s5u_teid->teid); - bearer->pgw_s5u_addr = pgw_s5u_teid->ipv4_addr; + tunnel->remote_teid = ntohl(pgw_s5u_teid->teid); + tunnel->remote_addr = pgw_s5u_teid->ipv4_addr; rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence = 0; /* Send Control Plane(UL) : SGW-S11 */ @@ -91,8 +94,8 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact, memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t)); sgw_s1u_teid.ipv4 = 1; sgw_s1u_teid.interface_type = GTP_F_TEID_S1_U_SGW_GTP_U; - sgw_s1u_teid.ipv4_addr = bearer->sgw_s1u_addr; - sgw_s1u_teid.teid = htonl(bearer->sgw_s1u_teid); + sgw_s1u_teid.ipv4_addr = tunnel->local_addr; + sgw_s1u_teid.teid = htonl(tunnel->local_teid); rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence = 1; rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = &sgw_s1u_teid; rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN; @@ -187,6 +190,7 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact, status_t rv; gtp_xact_t *s11_xact = NULL; sgw_bearer_t *bearer = NULL; + sgw_tunnel_t *tunnel = NULL; gtp_create_bearer_request_t *req = NULL; pkbuf_t *pkbuf = NULL; sgw_ue_t *sgw_ue = NULL; @@ -225,20 +229,22 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact, bearer = sgw_bearer_add(sess); d_assert(bearer, return, "No Bearer Context"); + tunnel = sgw_direct_tunnel_in_bearer(bearer); + d_assert(tunnel, return, "No Tunnel Context"); /* Receive Data Plane(UL) : PGW-S5U */ pgw_s5u_teid = req->bearer_contexts.s5_s8_u_sgw_f_teid.data; d_assert(pgw_s5u_teid, return, "Null param"); - bearer->pgw_s5u_teid = ntohl(pgw_s5u_teid->teid); - bearer->pgw_s5u_addr = pgw_s5u_teid->ipv4_addr; + tunnel->remote_teid = ntohl(pgw_s5u_teid->teid); + tunnel->remote_addr = pgw_s5u_teid->ipv4_addr; req->bearer_contexts.s5_s8_u_sgw_f_teid.presence = 0; /* Send Data Plane(UL) : SGW-S1U */ memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t)); sgw_s1u_teid.ipv4 = 1; sgw_s1u_teid.interface_type = GTP_F_TEID_S1_U_SGW_GTP_U; - sgw_s1u_teid.ipv4_addr = bearer->sgw_s1u_addr; - sgw_s1u_teid.teid = htonl(bearer->sgw_s1u_teid); + sgw_s1u_teid.ipv4_addr = tunnel->local_addr; + sgw_s1u_teid.teid = htonl(tunnel->local_teid); req->bearer_contexts.s1_u_enodeb_f_teid.presence = 1; req->bearer_contexts.s1_u_enodeb_f_teid.data = &sgw_s1u_teid; req->bearer_contexts.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN; @@ -258,6 +264,6 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact, d_assert(rv == CORE_OK, return, "xact_commit error"); d_trace(3, "[GTP] Create Bearer Request : SGW[%d] <-- PGW[%d]\n", - bearer->sgw_s1u_teid, bearer->pgw_s5u_teid); + tunnel->local_teid, tunnel->remote_teid); }