From c300d2b99addca777cd5a667eeed702ba1502f62 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 2 Dec 2017 00:44:07 +0900 Subject: [PATCH] MME GTPC Server done --- lib/gtp/gtp_node.c | 2 ++ lib/gtp/gtp_node.h | 2 ++ lib/gtp/gtp_types.h | 5 +++++ src/app/context.c | 15 +++++++++++++++ src/mme/mme_context.c | 11 +++++------ src/mme/mme_context.h | 14 ++++++++------ src/mme/mme_gtp_path.c | 27 +++++++++++++++++++++++---- src/mme/mme_s11_build.c | 32 +++++++++++++++++++++++++++++--- test/testpacket.c | 6 +++--- 9 files changed, 92 insertions(+), 22 deletions(-) diff --git a/lib/gtp/gtp_node.c b/lib/gtp/gtp_node.c index 16c6f8400..e24c1bfae 100644 --- a/lib/gtp/gtp_node.c +++ b/lib/gtp/gtp_node.c @@ -1,3 +1,5 @@ #define TRACE_MODULE _gtp_node +#include "core_debug.h" + #include "gtp_node.h" diff --git a/lib/gtp/gtp_node.h b/lib/gtp/gtp_node.h index 267fcb108..01fd38f57 100644 --- a/lib/gtp/gtp_node.h +++ b/lib/gtp/gtp_node.h @@ -4,6 +4,8 @@ #include "core_list.h" #include "core_network.h" +#include "gtp_types.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ diff --git a/lib/gtp/gtp_types.h b/lib/gtp/gtp_types.h index 16e2ba7d2..1fbcc37ce 100644 --- a/lib/gtp/gtp_types.h +++ b/lib/gtp/gtp_types.h @@ -342,6 +342,7 @@ CORE_DECLARE(c_int16_t) gtp_build_uli( #define GTP_F_TEID_IPV4_LEN 9 #define GTP_F_TEID_IPV6_LEN 21 +#define GTP_F_TEID_IPV4_AND_IPV6_LEN 25 typedef struct _gtp_f_teid_t { ED3(c_uint8_t ipv4:1;, c_uint8_t ipv6:1;, @@ -350,6 +351,10 @@ ED3(c_uint8_t ipv4:1;, union { c_uint32_t ipv4_addr; c_uint8_t ipv6_addr[IPV6_LEN]; + struct { + c_uint32_t ipv4_addr; + c_uint8_t ipv6_addr[IPV6_LEN]; + } both; }; } __attribute__ ((packed)) gtp_f_teid_t; diff --git a/src/app/context.c b/src/app/context.c index 3c2f0a671..ca6367672 100644 --- a/src/app/context.c +++ b/src/app/context.c @@ -86,6 +86,17 @@ static status_t context_prepare() return CORE_OK; } +static status_t context_validation() +{ + if (self.parameter.no_ipv4 == 1 && self.parameter.no_ipv6 == 1) + { + d_error("Both `no_ipv4` and `no_ipv6` set to `true` in `%s`", + context_self()->config.path); + return CORE_ERROR; + } + + return CORE_OK; +} status_t context_parse_config() { status_t rv; @@ -239,6 +250,10 @@ status_t context_parse_config() } } } + + rv = context_validation(); + if (rv != CORE_OK) return rv; + return CORE_OK; } diff --git a/src/mme/mme_context.c b/src/mme/mme_context.c index d78e21a07..df73bcc91 100644 --- a/src/mme/mme_context.c +++ b/src/mme/mme_context.c @@ -148,7 +148,9 @@ static status_t mme_context_validation() context_self()->config.path); return CORE_ERROR; } - if (self.gtpc_addr == 0) + + if (list_first(&self.gtpc4_list) == NULL && + list_first(&self.gtpc6_list) == NULL) { d_error("No mme.gtpc in '%s'", context_self()->config.path); @@ -382,10 +384,6 @@ status_t mme_context_parse_config() else if (!strcmp(gtpc_key, "hostname")) { hostname = yaml_iter_value(>pc_iter); -#if 1 - if (hostname) - self.gtpc_addr = inet_addr(hostname); -#endif } else if (!strcmp(gtpc_key, "port")) { @@ -1525,7 +1523,8 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue) list_init(&mme_ue->sess_list); mme_ue->mme_s11_teid = mme_ue->index; - mme_ue->mme_s11_addr = mme_self()->gtpc_addr; + mme_ue->mme_s11_ipv4 = mme_self()->gtpc4_addr; + mme_ue->mme_s11_ipv6 = mme_self()->gtpc6_addr; /* Create t3413 timer */ mme_ue->t3413 = timer_create(&self.tm_service, MME_EVT_EMM_T3413, diff --git a/src/mme/mme_context.h b/src/mme/mme_context.h index 46983c51c..9ed4348a0 100644 --- a/src/mme/mme_context.h +++ b/src/mme/mme_context.h @@ -57,13 +57,14 @@ typedef struct _mme_context_t { const char *fd_conf_path; /* MME freeDiameter conf path */ list_t s1ap_list; /* MME S1AP Server List */ - c_socklist_t gtpc4_list; /* MME GTPC IPv4 Server List */ - c_socklist_t gtpc6_list; /* MME GTPC IPv6 Server List */ list_t sgw_list; /* SGW GTPC Client List */ - c_uint32_t gtpc_addr; /* MME GTPC local address */ - c_uint16_t gtpc_port; /* MME GTPC local port */ - sock_id gtpc_sock; /* MME GTPC local listen socket */ + c_uint16_t gtpc_port; /* Default GTPC Port */ + + c_socklist_t gtpc4_list; /* MME GTPC IPv4 Server List */ + c_sockaddr_t *gtpc4_addr; /* MME GTPC IPv4 Address */ + c_socklist_t gtpc6_list; /* MME GTPC IPv6 Server List */ + c_sockaddr_t *gtpc6_addr; /* MME GTPC IPv6 Address */ c_uint32_t s5c_addr; /* PGW S5C remote address */ c_uint16_t s5c_port; /* PGW S5C remote port */ @@ -193,7 +194,8 @@ struct _mme_ue_t { /* IMPORTANT! * MME-S11-TEID is same with an index */ c_uint32_t mme_s11_teid; - c_uint32_t mme_s11_addr; + c_sockaddr_t *mme_s11_ipv4; /* MME S11 IPv4 Address */ + c_sockaddr_t *mme_s11_ipv6; /* MME S11 IPv6 Address */ c_uint32_t sgw_s11_teid; c_uint32_t sgw_s11_addr; diff --git a/src/mme/mme_gtp_path.c b/src/mme/mme_gtp_path.c index 2bf30aaa6..cc6a47c81 100644 --- a/src/mme/mme_gtp_path.c +++ b/src/mme/mme_gtp_path.c @@ -61,7 +61,16 @@ status_t mme_gtp_open() temp = node->sock; /* FIXME ADDR : Shoud be removed */ } -#if 0 + for (node = list_first(&mme_self()->gtpc4_list); + node; node = list_next(node)) + { + mme_self()->gtpc4_addr = sock_local_addr(node->sock); + if (mme_self()->gtpc4_addr) + { + break; + } + } + for (node = list_first(&mme_self()->gtpc6_list); node; node = list_next(node)) { @@ -72,7 +81,19 @@ status_t mme_gtp_open() return rv; } } -#endif + + for (node = list_first(&mme_self()->gtpc6_list); + node; node = list_next(node)) + { + mme_self()->gtpc6_addr = sock_local_addr(node->sock); + if (mme_self()->gtpc6_addr) + { + break; + } + } + + d_assert(mme_self()->gtpc4_addr || mme_self()->gtpc6_addr, + return CORE_ERROR, "No GTP Server"); /* FIXME : socket descriptor needs in gnode when packet is sending initilly */ while(sgw) @@ -94,13 +115,11 @@ status_t mme_gtp_close() sock_delete(node->sock); } -#if 0 for (node = list_first(&mme_self()->gtpc6_list); node; node = list_next(node)) { sock_delete(node->sock); } -#endif return CORE_OK; } diff --git a/src/mme/mme_s11_build.c b/src/mme/mme_s11_build.c index 758e89f14..dd883f263 100644 --- a/src/mme/mme_s11_build.c +++ b/src/mme/mme_s11_build.c @@ -71,13 +71,39 @@ status_t mme_s11_build_create_session_request( req->rat_type.u8 = GTP_RAT_TYPE_EUTRAN; memset(&mme_s11_teid, 0, sizeof(gtp_f_teid_t)); - mme_s11_teid.ipv4 = 1; mme_s11_teid.interface_type = GTP_F_TEID_S11_MME_GTP_C; mme_s11_teid.teid = htonl(mme_ue->mme_s11_teid); - mme_s11_teid.ipv4_addr = mme_ue->mme_s11_addr; + if (mme_ue->mme_s11_ipv4 && mme_ue->mme_s11_ipv6) + { + mme_s11_teid.ipv4 = 1; + mme_s11_teid.both.ipv4_addr = mme_ue->mme_s11_ipv4->sin.sin_addr.s_addr; + mme_s11_teid.ipv6 = 1; + memcpy(mme_s11_teid.both.ipv6_addr, + mme_ue->mme_s11_ipv6->sin6.sin6_addr.s6_addr, + sizeof(mme_s11_teid.ipv6_addr)); + req->sender_f_teid_for_control_plane.len = + GTP_F_TEID_IPV4_AND_IPV6_LEN; + } + else if (mme_ue->mme_s11_ipv4) + { + mme_s11_teid.ipv4 = 1; + mme_s11_teid.ipv4_addr = mme_ue->mme_s11_ipv4->sin.sin_addr.s_addr; + req->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN; + } + else if (mme_ue->mme_s11_ipv6) + { + mme_s11_teid.ipv4 = 1; + mme_s11_teid.both.ipv4_addr = mme_ue->mme_s11_ipv4->sin.sin_addr.s_addr; + mme_s11_teid.ipv6 = 1; + memcpy(mme_s11_teid.ipv6_addr, + mme_ue->mme_s11_ipv6->sin6.sin6_addr.s6_addr, + sizeof(mme_s11_teid.ipv6_addr)); + req->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV6_LEN; + } + else + d_assert(0, return CORE_ERROR,); req->sender_f_teid_for_control_plane.presence = 1; req->sender_f_teid_for_control_plane.data = &mme_s11_teid; - req->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN; memset(&pgw_s5c_teid, 0, sizeof(gtp_f_teid_t)); pgw_s5c_teid.ipv4 = 1; diff --git a/test/testpacket.c b/test/testpacket.c index 537499684..1f53b2db3 100644 --- a/test/testpacket.c +++ b/test/testpacket.c @@ -50,11 +50,11 @@ status_t testgtpu_enb_connect(sock_id *new) if (test_only_control_plane) return CORE_OK; + d_assert(mme, return CORE_ERROR,); + d_assert(mme->gtpc4_addr, return CORE_ERROR,); if (!mme) return CORE_ERROR; - memset(&addr, 0, sizeof(c_sockaddr_t)); - addr.sin.sin_addr.s_addr = mme->gtpc_addr; - addr.c_sa_family = AF_INET; + memcpy(&addr, mme->gtpc4_addr, sizeof(c_sockaddr_t)); addr.c_sa_port = htons(GTPV1_U_UDP_PORT); rv = udp_socket(new, AF_INET);