diff --git a/lib/core/include/3gpp_types.h b/lib/core/include/3gpp_types.h index 71df3ac110..029fd16ade 100644 --- a/lib/core/include/3gpp_types.h +++ b/lib/core/include/3gpp_types.h @@ -14,6 +14,9 @@ extern "C" { #define SCTP_S1AP_PPID 18 #define SCTP_X2AP_PPID 27 +#define MAX_NUM_OF_SGW 32 +#define MAX_NUM_OF_PGW 32 + #define MAX_NUM_OF_ENB 128 #define MAX_NUM_OF_UE 128 #define MAX_NUM_OF_SESS 4 diff --git a/lib/gtp/gtp_node.c b/lib/gtp/gtp_node.c index ca19c50a1e..abf434c131 100644 --- a/lib/gtp/gtp_node.c +++ b/lib/gtp/gtp_node.c @@ -28,14 +28,13 @@ status_t gtp_node_final(void) return CORE_OK; } -status_t gtp_add_node(list_t *list, gtp_node_t **node, +status_t gtp_create_node(gtp_node_t **node, c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4) { status_t rv; gtp_node_t *new_node = NULL; c_sockaddr_t *preferred_list = NULL; - d_assert(list, return CORE_ERROR,); d_assert(all_list, return CORE_ERROR,); rv = core_copyaddrinfo(&preferred_list, all_list); @@ -71,8 +70,6 @@ status_t gtp_add_node(list_t *list, gtp_node_t **node, list_init(&new_node->local_list); list_init(&new_node->remote_list); - - list_append(list, new_node); } *node = new_node; @@ -80,7 +77,22 @@ status_t gtp_add_node(list_t *list, gtp_node_t **node, return CORE_OK; } -gtp_node_t *gtp_add_node_with_teid(list_t *list, gtp_f_teid_t *f_teid, +status_t gtp_delete_node(gtp_node_t *node) +{ + d_assert(node, return CORE_ERROR,); + + if (node->sock) + sock_delete(node->sock); + + gtp_xact_delete_all(node); + + core_freeaddrinfo(node->sa_list); + pool_free_node(>p_node_pool, node); + + return CORE_OK; +} + +gtp_node_t *gtp_add_node(list_t *list, gtp_f_teid_t *f_teid, c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4) { status_t rv; @@ -94,9 +106,16 @@ gtp_node_t *gtp_add_node_with_teid(list_t *list, gtp_f_teid_t *f_teid, rv = gtp_f_teid_to_sockaddr(f_teid, port, &sa_list); d_assert(rv == CORE_OK, return NULL,); - rv = gtp_add_node(list, &node, sa_list, no_ipv4, no_ipv6, prefer_ipv4); + rv = gtp_create_node(&node, sa_list, no_ipv4, no_ipv6, prefer_ipv4); d_assert(rv == CORE_OK, return NULL,); - d_assert(node, return NULL,); + if (node == NULL) + { + d_error("Invalid Parameter : " + "port[%d], no_ipv4[%d], no_ipv6[%d], prefer_ipv4[%d]", + port, no_ipv4, no_ipv6, prefer_ipv4); + return NULL; + } + list_append(list, node); rv = gtp_f_teid_to_ip(f_teid, &node->ip); d_assert(rv == CORE_OK, return NULL,); @@ -111,19 +130,15 @@ gtp_node_t *gtp_add_node_with_teid(list_t *list, gtp_f_teid_t *f_teid, status_t gtp_remove_node(list_t *list, gtp_node_t *node) { + status_t rv; d_assert(node, return CORE_ERROR,); list_remove(list, node); - if (node->sock) - sock_delete(node->sock); + rv = gtp_delete_node(node); + d_assert(rv == CORE_OK, return CORE_ERROR,); - gtp_xact_delete_all(node); - - core_freeaddrinfo(node->sa_list); - pool_free_node(>p_node_pool, node); - - return CORE_OK; + return rv; } status_t gtp_remove_all_nodes(list_t *list) diff --git a/lib/gtp/gtp_node.h b/lib/gtp/gtp_node.h index b24c3b6e7a..2da8dc7c87 100644 --- a/lib/gtp/gtp_node.h +++ b/lib/gtp/gtp_node.h @@ -35,9 +35,11 @@ typedef struct _gtp_node_t { CORE_DECLARE(status_t) gtp_node_init(void); CORE_DECLARE(status_t) gtp_node_final(void); -CORE_DECLARE(status_t) gtp_add_node(list_t *list, gtp_node_t **node, - c_sockaddr_t *sa_list, int no_ipv4, int no_ipv6, int prefer_ipv4); -CORE_DECLARE(gtp_node_t *) gtp_add_node_with_teid( +CORE_DECLARE(status_t) gtp_create_node(gtp_node_t **node, + c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4); +CORE_DECLARE(status_t) gtp_delete_node(gtp_node_t *node); + +CORE_DECLARE(gtp_node_t *) gtp_add_node( list_t *list, gtp_f_teid_t *f_teid, c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4); CORE_DECLARE(status_t) gtp_remove_node(list_t *list, gtp_node_t *node); diff --git a/src/mme/mme_context.c b/src/mme/mme_context.c index a8977f1c1c..04fcab4a4d 100644 --- a/src/mme/mme_context.c +++ b/src/mme/mme_context.c @@ -29,6 +29,9 @@ static mme_context_t self; static fd_config_t g_fd_conf; +pool_declare(mme_sgw_pool, mme_sgw_t, MAX_NUM_OF_SGW); +pool_declare(mme_pgw_pool, mme_pgw_t, MAX_NUM_OF_PGW); + index_declare(mme_enb_pool, mme_enb_t, MAX_NUM_OF_ENB); index_declare(mme_ue_pool, mme_ue_t, MAX_POOL_OF_UE); index_declare(enb_ue_pool, enb_ue_t, MAX_POOL_OF_UE); @@ -59,6 +62,9 @@ status_t mme_context_init() list_init(&self.sgw_list); list_init(&self.pgw_list); + pool_init(&mme_sgw_pool, MAX_NUM_OF_SGW); + pool_init(&mme_pgw_pool, MAX_NUM_OF_PGW); + index_init(&mme_enb_pool, MAX_NUM_OF_ENB); index_init(&mme_ue_pool, MAX_POOL_OF_UE); @@ -121,8 +127,12 @@ status_t mme_context_final() index_final(&mme_enb_pool); - gtp_remove_all_nodes(&self.sgw_list); - gtp_remove_all_nodes(&self.pgw_list); + mme_sgw_remove_all(); + mme_pgw_remove_all(); + + pool_final(&mme_sgw_pool); + pool_final(&mme_pgw_pool); + gtp_node_final(); sock_remove_all_nodes(&self.s1ap_list); @@ -1280,7 +1290,7 @@ status_t mme_context_parse_config() yaml_iter_recurse(&mme_iter, >pc_array); do { - gtp_node_t *sgw = NULL; + mme_sgw_t *sgw = NULL; c_sockaddr_t *list = NULL; int family = AF_UNSPEC; int i, num = 0; @@ -1368,11 +1378,11 @@ status_t mme_context_parse_config() d_assert(rv == CORE_OK, return CORE_ERROR,); } - rv = gtp_add_node(&self.sgw_list, &sgw, list, + sgw = mme_sgw_add(list, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); - d_assert(rv == CORE_OK, return CORE_ERROR,); + d_assert(sgw, return CORE_ERROR,); core_freeaddrinfo(list); @@ -1394,7 +1404,7 @@ status_t mme_context_parse_config() yaml_iter_recurse(&mme_iter, >pc_array); do { - gtp_node_t *pgw = NULL; + mme_pgw_t *pgw = NULL; c_sockaddr_t *list = NULL; int family = AF_UNSPEC; int i, num = 0; @@ -1482,11 +1492,11 @@ status_t mme_context_parse_config() d_assert(rv == CORE_OK, return CORE_ERROR,); } - rv = gtp_add_node(&self.pgw_list, &pgw, list, + pgw = mme_pgw_add(list, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, context_self()->parameter.prefer_ipv4); - d_assert(rv == CORE_OK, return CORE_ERROR,); + d_assert(pgw, return CORE_ERROR,); core_freeaddrinfo(list); @@ -1595,6 +1605,122 @@ status_t mme_context_setup_trace_module() return CORE_OK; } +mme_sgw_t *mme_sgw_add( + c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4) +{ + status_t rv; + mme_sgw_t *sgw = NULL; + + d_assert(all_list, return NULL, "Null param"); + + pool_alloc_node(&mme_sgw_pool, &sgw); + d_assert(sgw, return NULL, "Null param"); + + rv = gtp_create_node(&sgw->gnode, all_list, no_ipv4, no_ipv6, prefer_ipv4); + d_assert(rv == CORE_OK, return NULL,); + if (sgw->gnode == NULL) + { + d_error("Invalid Parameter : " + "no_ipv4[%d], no_ipv6[%d], prefer_ipv4[%d]", + no_ipv4, no_ipv6, prefer_ipv4); + return NULL; + } + + list_append(&self.sgw_list, sgw); + + return sgw; +} + +status_t mme_sgw_remove(mme_sgw_t *sgw) +{ + status_t rv; + d_assert(sgw, return CORE_ERROR, "Null param"); + + list_remove(&self.sgw_list, sgw); + + rv = gtp_delete_node(sgw->gnode); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + pool_free_node(&mme_sgw_pool, sgw); + + return CORE_OK; +} + +status_t mme_sgw_remove_all() +{ + mme_sgw_t *sgw = NULL, *next_sgw = NULL; + + sgw = list_first(&self.sgw_list); + while (sgw) + { + next_sgw = list_next(sgw); + + mme_sgw_remove(sgw); + + sgw = next_sgw; + } + + return CORE_OK; +} + +mme_pgw_t *mme_pgw_add( + c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4) +{ + status_t rv; + mme_pgw_t *pgw = NULL; + + d_assert(all_list, return NULL, "Null param"); + + pool_alloc_node(&mme_pgw_pool, &pgw); + d_assert(pgw, return NULL, "Null param"); + + rv = gtp_create_node(&pgw->gnode, all_list, no_ipv4, no_ipv6, prefer_ipv4); + d_assert(rv == CORE_OK, return NULL,); + if (pgw->gnode == NULL) + { + d_error("Invalid Parameter : " + "no_ipv4[%d], no_ipv6[%d], prefer_ipv4[%d]", + no_ipv4, no_ipv6, prefer_ipv4); + return NULL; + } + + list_append(&self.pgw_list, pgw); + + return pgw; +} + +status_t mme_pgw_remove(mme_pgw_t *pgw) +{ + status_t rv; + d_assert(pgw, return CORE_ERROR, "Null param"); + + list_remove(&self.pgw_list, pgw); + + rv = gtp_delete_node(pgw->gnode); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + pool_free_node(&mme_pgw_pool, pgw); + + return CORE_OK; +} + +status_t mme_pgw_remove_all() +{ + mme_pgw_t *pgw = NULL, *next_pgw = NULL; + + pgw = list_first(&self.pgw_list); + while (pgw) + { + next_pgw = list_next(pgw); + + mme_pgw_remove(pgw); + + pgw = next_pgw; + } + + return CORE_OK; +} + mme_enb_t* mme_enb_add(sock_id sock, c_sockaddr_t *addr) { mme_enb_t *enb = NULL; @@ -1950,7 +2076,7 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue) if (mme_self()->sgw == NULL) mme_self()->sgw = list_first(&mme_self()->sgw_list); - SETUP_GTP_NODE(mme_ue, mme_self()->sgw); + SETUP_GTP_NODE(mme_ue, mme_self()->sgw->gnode); mme_self()->sgw = list_next(mme_self()->sgw); diff --git a/src/mme/mme_context.h b/src/mme/mme_context.h index 852c082cfa..7403801e85 100644 --- a/src/mme/mme_context.h +++ b/src/mme/mme_context.h @@ -34,6 +34,9 @@ extern "C" { #define MAX_NUM_OF_BPLMN 6 +typedef struct _mme_sgw_t mme_sgw_t; +typedef struct _mme_pgw_t mme_pgw_t; + typedef struct _enb_ue_t enb_ue_t; typedef struct _mme_ue_t mme_ue_t; @@ -72,7 +75,7 @@ typedef struct _mme_context_t { c_sockaddr_t *gtpc_addr6; /* MME GTPC IPv6 Address */ list_t sgw_list; /* SGW GTPC Client List */ - gtp_node_t *sgw; /* Iterator for SGW round-robin */ + mme_sgw_t *sgw; /* Iterator for SGW round-robin */ list_t pgw_list; /* PGW GTPC Client List */ c_sockaddr_t *pgw_addr; /* First IPv4 Address Selected */ @@ -140,6 +143,18 @@ typedef struct _mme_context_t { } mme_context_t; +typedef struct _mme_sgw_t { + lnode_t node; + + gtp_node_t *gnode; +} mme_sgw_t; + +typedef struct _mme_pgw_t { + lnode_t node; + + gtp_node_t *gnode; +} mme_pgw_t; + typedef struct _mme_enb_t { index_t index; /* An index of this node */ fsm_t sm; /* A state machine */ @@ -509,6 +524,16 @@ CORE_DECLARE(mme_context_t*) mme_self(void); CORE_DECLARE(status_t) mme_context_parse_config(void); CORE_DECLARE(status_t) mme_context_setup_trace_module(void); +CORE_DECLARE(mme_sgw_t*) mme_sgw_add( + c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4); +CORE_DECLARE(status_t ) mme_sgw_remove(mme_sgw_t *sgw); +CORE_DECLARE(status_t ) mme_sgw_remove_all(); + +CORE_DECLARE(mme_pgw_t*) mme_pgw_add( + c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4); +CORE_DECLARE(status_t ) mme_pgw_remove(mme_pgw_t *pgw); +CORE_DECLARE(status_t ) mme_pgw_remove_all(); + CORE_DECLARE(mme_enb_t*) mme_enb_add(sock_id sock, c_sockaddr_t *addr); CORE_DECLARE(status_t) mme_enb_remove(mme_enb_t *enb); CORE_DECLARE(status_t) mme_enb_remove_all(void); diff --git a/src/mme/mme_gtp_path.c b/src/mme/mme_gtp_path.c index b8a266a99c..ec2e26098b 100644 --- a/src/mme/mme_gtp_path.c +++ b/src/mme/mme_gtp_path.c @@ -43,14 +43,15 @@ static int _gtpv2_c_recv_cb(sock_id sock, void *data) return 0; } -static c_sockaddr_t *gtp_addr_find_by_family(list_t *list, int family) +static c_sockaddr_t *pgw_addr_find_by_family(list_t *list, int family) { - gtp_node_t *gnode = NULL; + mme_pgw_t *pgw = NULL; d_assert(list, return NULL,); - for (gnode = list_first(list); gnode; gnode = list_next(gnode)) + for (pgw = list_first(list); pgw; pgw = list_next(pgw)) { - c_sockaddr_t *addr = gnode->sa_list; + d_assert(pgw->gnode, return NULL,); + c_sockaddr_t *addr = pgw->gnode->sa_list; while(addr) { if (addr->c_sa_family == family) @@ -67,7 +68,7 @@ static c_sockaddr_t *gtp_addr_find_by_family(list_t *list, int family) status_t mme_gtp_open() { status_t rv; - gtp_node_t *gnode = NULL; + mme_sgw_t *sgw = NULL; rv = gtp_server_list(&mme_self()->gtpc_list, _gtpv2_c_recv_cb); d_assert(rv == CORE_OK, return CORE_ERROR,); @@ -82,17 +83,16 @@ status_t mme_gtp_open() d_assert(mme_self()->gtpc_addr || mme_self()->gtpc_addr6, return CORE_ERROR, "No GTP Server"); - mme_self()->pgw_addr = gtp_addr_find_by_family( + mme_self()->pgw_addr = pgw_addr_find_by_family( &mme_self()->pgw_list, AF_INET); - mme_self()->pgw_addr6 = gtp_addr_find_by_family( + mme_self()->pgw_addr6 = pgw_addr_find_by_family( &mme_self()->pgw_list, AF_INET6); d_assert(mme_self()->pgw_addr || mme_self()->pgw_addr6, return CORE_ERROR,); - for (gnode = list_first(&mme_self()->sgw_list); - gnode; gnode = list_next(gnode)) + for (sgw = list_first(&mme_self()->sgw_list); sgw; sgw = list_next(sgw)) { - rv = gtp_client(gnode); + rv = gtp_client(sgw->gnode); d_assert(rv == CORE_OK, return CORE_ERROR,); } diff --git a/src/pgw/pgw_context.c b/src/pgw/pgw_context.c index 538ba73b83..579522f4a0 100644 --- a/src/pgw/pgw_context.c +++ b/src/pgw/pgw_context.c @@ -1082,7 +1082,7 @@ gtp_node_t *pgw_sgw_add_by_message(gtp_message_t *message) sgw = gtp_find_node(&pgw_self()->sgw_s5c_list, sgw_s5c_teid); if (!sgw) { - sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5c_list, sgw_s5c_teid, + sgw = gtp_add_node(&pgw_self()->sgw_s5c_list, sgw_s5c_teid, pgw_self()->gtpc_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, diff --git a/src/pgw/pgw_s5c_handler.c b/src/pgw/pgw_s5c_handler.c index bf5c0ab233..362267dfed 100644 --- a/src/pgw/pgw_s5c_handler.c +++ b/src/pgw/pgw_s5c_handler.c @@ -86,7 +86,7 @@ void pgw_s5c_handle_create_session_request( sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid); if (!sgw) { - sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, + sgw = gtp_add_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, pgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, @@ -190,7 +190,7 @@ void pgw_s5c_handle_create_bearer_response( sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid); if (!sgw) { - sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, + sgw = gtp_add_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid, pgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, diff --git a/src/sgw/sgw_context.c b/src/sgw/sgw_context.c index 08043ccbc2..9e8d51f196 100644 --- a/src/sgw/sgw_context.c +++ b/src/sgw/sgw_context.c @@ -514,7 +514,7 @@ gtp_node_t *sgw_mme_add_by_message(gtp_message_t *message) mme = gtp_find_node(&sgw_self()->mme_s11_list, mme_s11_teid); if (!mme) { - mme = gtp_add_node_with_teid(&sgw_self()->mme_s11_list, mme_s11_teid, + mme = gtp_add_node(&sgw_self()->mme_s11_list, mme_s11_teid, sgw_self()->gtpc_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, diff --git a/src/sgw/sgw_s11_handler.c b/src/sgw/sgw_s11_handler.c index 1f7b25d844..0cc24551d4 100644 --- a/src/sgw/sgw_s11_handler.c +++ b/src/sgw/sgw_s11_handler.c @@ -120,7 +120,7 @@ void sgw_s11_handle_create_session_request( pgw = gtp_find_node(&sgw_self()->pgw_s5c_list, pgw_s5c_teid); if (!pgw) { - pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5c_list, pgw_s5c_teid, + pgw = gtp_add_node(&sgw_self()->pgw_s5c_list, pgw_s5c_teid, sgw_self()->gtpc_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, @@ -227,7 +227,7 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact, enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid); if (!enb) { - enb = gtp_add_node_with_teid(&sgw_self()->enb_s1u_list, enb_s1u_teid, + enb = gtp_add_node(&sgw_self()->enb_s1u_list, enb_s1u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, @@ -460,7 +460,7 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact, enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid); if (!enb) { - enb = gtp_add_node_with_teid(&sgw_self()->enb_s1u_list, enb_s1u_teid, + enb = gtp_add_node(&sgw_self()->enb_s1u_list, enb_s1u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, @@ -830,8 +830,7 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request( enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid); if (!enb) { - enb = gtp_add_node_with_teid( - &sgw_self()->enb_s1u_list, req_teid, + enb = gtp_add_node(&sgw_self()->enb_s1u_list, req_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, @@ -871,8 +870,7 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request( enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid); if (!enb) { - enb = gtp_add_node_with_teid( - &sgw_self()->enb_s1u_list, req_teid, + enb = gtp_add_node(&sgw_self()->enb_s1u_list, req_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, diff --git a/src/sgw/sgw_s5c_handler.c b/src/sgw/sgw_s5c_handler.c index 863629441e..3954b35864 100644 --- a/src/sgw/sgw_s5c_handler.c +++ b/src/sgw/sgw_s5c_handler.c @@ -98,7 +98,7 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact, pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid); if (!pgw) { - pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, + pgw = gtp_add_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6, @@ -286,7 +286,7 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact, pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid); if (!pgw) { - pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, + pgw = gtp_add_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid, sgw_self()->gtpu_port, context_self()->parameter.no_ipv4, context_self()->parameter.no_ipv6,