From 5c4c4498d2a968758351a3370842136a0892cade Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Oct 2017 00:44:09 +0900 Subject: [PATCH] logging disunite to each individual --- configure.ac | 1 - lib/Makefile.am | 2 +- lib/base/context.c | 206 ++++++++++++++-------------- lib/base/context.h | 17 ++- lib/core/include/core_debug.h | 15 +- lib/core/src/debug.c | 244 ++++++++++++++++++++++++++------- lib/core/src/unix/start.c | 2 - lib/logger/logger.c | 4 - src/Makefile.am | 13 -- src/epc.c | 16 +-- src/init.c | 68 ++++----- support/config/hss.conf.in | 23 ++-- support/config/mme.conf.in | 113 ++++++++------- support/config/nextepc.conf.in | 142 ++++++++++--------- support/config/pcrf.conf.in | 24 ++-- support/config/pgw.conf.in | 48 ++++--- support/config/sgw.conf.in | 26 ++-- 17 files changed, 563 insertions(+), 401 deletions(-) diff --git a/configure.ac b/configure.ac index 0007115f4..836e88fa7 100644 --- a/configure.ac +++ b/configure.ac @@ -432,7 +432,6 @@ AC_CONFIG_FILES([lib/core/src/Makefile]) AC_CONFIG_FILES([lib/core/src/unix/Makefile]) AC_CONFIG_FILES([lib/core/test/Makefile]) AC_CONFIG_FILES([lib/core/Makefile]) -AC_CONFIG_FILES([lib/logger/Makefile]) AC_CONFIG_FILES([lib/base/Makefile]) AC_CONFIG_FILES([lib/s1ap/asn1c/Makefile]) AC_CONFIG_FILES([lib/s1ap/Makefile]) diff --git a/lib/Makefile.am b/lib/Makefile.am index 1809e1182..7345bc88d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = @FREEDIAMETER_DIR@ core logger base s1ap nas fd gtp ipfw +SUBDIRS = @FREEDIAMETER_DIR@ core base s1ap nas fd gtp ipfw MAINTAINERCLEANFILES = Makefile.in MOSTLYCLEANFILES = *.stackdump diff --git a/lib/base/context.c b/lib/base/context.c index 0bce1f5e3..5e46a72b3 100644 --- a/lib/base/context.c +++ b/lib/base/context.c @@ -2,6 +2,7 @@ #include "core_file.h" #include "core_debug.h" +#include "core_lib.h" #include #include "context.h" @@ -27,6 +28,9 @@ status_t context_final() d_assert(context_initialized == 1, return CORE_ERROR, "Context already has been finalized"); + if (self.config.bson) + bson_destroy(self.config.bson); + context_initialized = 0; return CORE_OK; @@ -44,8 +48,9 @@ status_t context_read_file() status_t rv; file_t *file; - jsmn_parser parser; + bson_error_t error; size_t json_len; + jsmn_parser parser; int result; d_assert(config->path, return CORE_ERROR,); @@ -85,6 +90,13 @@ status_t context_read_file() return CORE_ERROR; } + config->bson = bson_new_from_json((const uint8_t *)config->json, -1, &error);; + if (config->bson == NULL) + { + d_fatal("Failed to parse configuration file '%s'", config->path); + return CORE_ERROR; + } + d_print(" Config '%s'\n", config->path); return CORE_OK; @@ -93,132 +105,126 @@ status_t context_read_file() status_t context_parse_config() { config_t *config = &self.config; + bson_iter_t iter, child1_iter, child2_iter; + c_uint32_t length = 0; - char *json = config->json; - jsmntok_t *token = config->token; + d_assert(config, return CORE_ERROR, ); - typedef enum { START, ROOT, SKIP, STOP } parse_state; - parse_state state = START; - - size_t root_tokens = 0; - size_t skip_tokens = 0; - size_t i, j, m, n; - - for (i = 0, j = 1; j > 0; i++, j--) + if (!bson_iter_init(&iter, config->bson)) { - jsmntok_t *t = &token[i]; + d_error("bson_iter_init failed in this document"); + return CORE_ERROR; + } - j += t->size; - - switch (state) + while(bson_iter_next(&iter)) + { + const char *key = bson_iter_key(&iter); + if (!strcmp(key, "DB_URI") && BSON_ITER_HOLDS_UTF8(&iter)) { - case START: + self.db_uri = bson_iter_utf8(&iter, &length); + } + else if (!strcmp(key, "LOG") && BSON_ITER_HOLDS_DOCUMENT(&iter)) + { + bson_iter_recurse(&iter, &child1_iter); + while(bson_iter_next(&child1_iter)) { - state = ROOT; - root_tokens = t->size; - - break; - } - case ROOT: - { - if (jsmntok_equal(json, t, "DB_URI") == 0) + const char *child1_key = bson_iter_key(&child1_iter); + if (!strcmp(child1_key, "FILE") && + BSON_ITER_HOLDS_UTF8(&child1_iter)) { - self.db_uri = jsmntok_to_string(json, t+1); + self.log.file = bson_iter_utf8(&child1_iter, &length); } - else if (jsmntok_equal(json, t, "LOG_PATH") == 0) + else if (!strcmp(child1_key, "SOCKET") && + BSON_ITER_HOLDS_DOCUMENT(&iter)) { - self.log_path = jsmntok_to_string(json, t+1); - } - else if (jsmntok_equal(json, t, "TRACE") == 0) - { - for (m = 1, n = 1; n > 0; m++, n--) + bson_iter_recurse(&child1_iter, &child2_iter); + while(bson_iter_next(&child2_iter)) { - n += (t+m)->size; - - char *v = jsmntok_to_string(json, t+m+1); - if (jsmntok_equal(json, t+m, "S1AP") == 0) + const char *child2_key = bson_iter_key(&child2_iter); + if (!strcmp(child2_key, "FILE") && + BSON_ITER_HOLDS_UTF8(&child2_iter)) { - if (v) self.trace_level.s1ap = atoi(v); + self.log.socket.file = + bson_iter_utf8(&child2_iter, &length); } - else if (jsmntok_equal(json, t+m, "NAS") == 0) + else if (!strcmp(child2_key, "UNIX_DOMAIN") && + BSON_ITER_HOLDS_UTF8(&child2_iter)) { - if (v) self.trace_level.nas = atoi(v); - } - else if (jsmntok_equal(json, t+m, "FD") == 0) - { - if (v) self.trace_level.fd = atoi(v); - } - else if (jsmntok_equal(json, t+m, "GTP") == 0) - { - if (v) self.trace_level.gtp = atoi(v); - } - else if (jsmntok_equal(json, t+m, "OTHERS") == 0) - { - if (v) self.trace_level.others = atoi(v); + self.log.socket.unix_domain = + bson_iter_utf8(&child2_iter, &length); } } + } - else if (jsmntok_equal(json, t, "NODE") == 0) + } + } + else if (!strcmp(key, "TRACE") && BSON_ITER_HOLDS_DOCUMENT(&iter)) + { + bson_iter_recurse(&iter, &child1_iter); + while(bson_iter_next(&child1_iter)) + { + const char *child1_key = bson_iter_key(&child1_iter); + if (!strcmp(child1_key, "S1AP") && + BSON_ITER_HOLDS_INT32(&child1_iter)) { - for (m = 1, n = 1; n > 0; m++, n--) - { - n += (t+m)->size; - - char *v = jsmntok_to_string(json, t+m+1); - if (jsmntok_equal(json, t+m, "DISABLE_HSS") == 0) - { - if (v) self.hidden.disable_hss = atoi(v); - } - else if (jsmntok_equal(json, t+m, "DISABLE_SGW") == 0) - { - if (v) self.hidden.disable_sgw = atoi(v); - } - else if (jsmntok_equal(json, t+m, "DISABLE_PGW") == 0) - { - if (v) self.hidden.disable_pgw = atoi(v); - } - else if (jsmntok_equal(json, t+m, "DISABLE_PCRF") == 0) - { - if (v) self.hidden.disable_pcrf = atoi(v); - } - } + self.trace_level.s1ap = bson_iter_int32(&child1_iter); + } + else if (!strcmp(child1_key, "NAS") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.trace_level.nas = bson_iter_int32(&child1_iter); + } + else if (!strcmp(child1_key, "FD") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.trace_level.fd = bson_iter_int32(&child1_iter); + } + else if (!strcmp(child1_key, "GTP") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.trace_level.gtp = bson_iter_int32(&child1_iter); + } + else if (!strcmp(child1_key, "OTHERS") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.trace_level.others = bson_iter_int32(&child1_iter); } - - state = SKIP; - skip_tokens = t->size; - - root_tokens--; - if (root_tokens == 0) state = STOP; - - break; } - case SKIP: + } + else if (!strcmp(key, "NODE") && BSON_ITER_HOLDS_DOCUMENT(&iter)) + { + bson_iter_recurse(&iter, &child1_iter); + while(bson_iter_next(&child1_iter)) { - skip_tokens += t->size; - - skip_tokens--; - if (skip_tokens == 0) state = ROOT; - - break; + const char *child1_key = bson_iter_key(&child1_iter); + if (!strcmp(child1_key, "DISABLE_HSS") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.node.disable_hss = bson_iter_int32(&child1_iter); + } + else if (!strcmp(child1_key, "DISABLE_SGW") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.node.disable_sgw = bson_iter_int32(&child1_iter); + } + else if (!strcmp(child1_key, "DISABLE_PGW") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.node.disable_pgw = bson_iter_int32(&child1_iter); + } + else if (!strcmp(child1_key, "DISABLE_PCRF") && + BSON_ITER_HOLDS_INT32(&child1_iter)) + { + self.node.disable_pcrf = bson_iter_int32(&child1_iter); + } } - case STOP: - { - break; - } - default: - { - d_error("Failed to parse configuration in the state(%u)", - state); - break; - } - } } return CORE_OK; } -status_t context_db_init(char *db_uri) +status_t context_db_init(const char *db_uri) { bson_t reply; bson_error_t error; diff --git a/lib/base/context.h b/lib/base/context.h index 8e0437dc9..952d633cb 100644 --- a/lib/base/context.h +++ b/lib/base/context.h @@ -16,6 +16,7 @@ typedef struct _config_t { char *path; char json[MAX_CONFIG_FILE_SIZE+1]; jsmntok_t token[MAX_NUM_OF_CONFIG_TOKEN]; + void *bson; } config_t; #define MAX_DB_URI_LEN 256 @@ -23,13 +24,19 @@ typedef struct _config_t { typedef struct _context_t { config_t config; - char *log_path; - - char *db_uri; + const char *db_uri; void *db_client; char *db_name; void *database; + struct { + const char *file; + struct { + const char *unix_domain; + const char *file; + } socket; + } log; + struct { int s1ap; int nas; @@ -43,7 +50,7 @@ typedef struct _context_t { int disable_sgw; int disable_pgw; int disable_pcrf; - } hidden; + } node; } context_t; @@ -55,7 +62,7 @@ CORE_DECLARE(status_t) context_read_file(void); CORE_DECLARE(status_t) context_parse_config(void); CORE_DECLARE(status_t) context_setup_trace_module(void); -CORE_DECLARE(status_t) context_db_init(char *db_uri); +CORE_DECLARE(status_t) context_db_init(const char *db_uri); CORE_DECLARE(status_t) context_db_final(void); #ifdef __cplusplus diff --git a/lib/core/include/core_debug.h b/lib/core/include/core_debug.h index e5a972ee5..d9d9a205f 100644 --- a/lib/core/include/core_debug.h +++ b/lib/core/include/core_debug.h @@ -25,9 +25,9 @@ extern int g_trace_mask; #define D_MSG_TO_CONSOLE 0x00000001 #define D_MSG_TO_STDOUT 0x00000002 #define D_MSG_TO_SYSLOG 0x00000004 -#define D_MSG_TO_LOGD 0x00000008 +#define D_MSG_TO_SOCKET 0x00000008 #define D_MSG_TO_ALL (D_MSG_TO_CONSOLE | D_MSG_TO_STDOUT | \ - D_MSG_TO_SYSLOG | D_MSG_TO_LOGD) + D_MSG_TO_SYSLOG | D_MSG_TO_SOCKET) #define D_LOG_LEVEL_NONE 0 #define D_LOG_LEVEL_FATAL 1 @@ -138,12 +138,11 @@ CORE_DECLARE(int) d_msg(int tp, int lv, c_time_t t, char *fn, int ln, expr; \ } -void d_msg_init(); - -void d_msg_final(); - +void d_msg_register_syslog(const char *name); +void d_msg_deregister_syslog(); +void d_msg_register_socket(const char *name, const char *log_file); +void d_msg_deregister_socket(); void d_msg_register_console(int console_fd); - void d_msg_deregister_console(); void d_msg_to(int to, int on_off); @@ -198,8 +197,6 @@ void d_trace_level(int *mod_name, int level); */ void d_trace_off(int *mod_name); -#define D_LOGD_IPC_PATH "/tmp/dlogmesg" - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lib/core/src/debug.c b/lib/core/src/debug.c index d72061411..fba1d9adc 100644 --- a/lib/core/src/debug.c +++ b/lib/core/src/debug.c @@ -1,6 +1,7 @@ #include "core_debug.h" #include "core_param.h" #include "core_file.h" +#include "core_thread.h" #include #include @@ -9,45 +10,192 @@ int g_trace_mask = 1; -int g_msg_to = D_MSG_TO_LOGD | D_MSG_TO_STDOUT; +int g_msg_to = D_MSG_TO_STDOUT; int g_console_connected = 0; int g_syslog_connected = 0; -int g_logd_connected = 0; +int g_socket_connected = 0; int g_log_level_console = D_LOG_LEVEL_FULL; int g_log_level_stdout = D_LOG_LEVEL_FULL; int g_log_level_syslog = D_LOG_LEVEL_FULL; -int g_log_level_logd = D_LOG_LEVEL_FULL; +int g_log_level_socket = D_LOG_LEVEL_FULL; -int g_console_fd = -1; -int g_logd_fd = -1; -struct sockaddr_un g_logd_addr; +static int g_console_fd = -1; +static int g_socket_fd = -1; +static struct sockaddr_un g_socket_addr; -void d_msg_init() +static thread_id socket_thread = 0; +static void *THREAD_FUNC socket_main(thread_id id, void *data); +static int socket_handler(const char *path); + +void d_msg_register_syslog(const char *name) { - openlog("libcore", 0, LOG_DAEMON); + d_assert(name, return, ); + openlog(name, 0, LOG_DAEMON); g_syslog_connected = 1; - - g_logd_fd = socket(AF_UNIX, SOCK_DGRAM, 0); - d_assert(g_logd_fd >= 0, return, - "socket() failed. (%d:%s)\n", errno, strerror(errno)); - - g_logd_addr.sun_family = AF_UNIX; - strcpy(g_logd_addr.sun_path, D_LOGD_IPC_PATH); - - g_logd_connected = 1; } -void d_msg_final() +void d_msg_deregister_syslog() { g_syslog_connected = 0; closelog(); +} - g_logd_connected = 0; - close(g_logd_fd); - g_logd_fd = -1; +void d_msg_register_socket(const char *name, const char *log_file) +{ + status_t rv; + + d_assert(name, return, ); + + g_socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0); + d_assert(g_socket_fd >= 0, return, + "socket() failed. (%d:%s)\n", errno, strerror(errno)); + + g_socket_addr.sun_family = AF_UNIX; + strcpy(g_socket_addr.sun_path, name); + + rv = thread_create(&socket_thread, NULL, socket_main, (void*)log_file); + d_assert(rv == CORE_OK, return, "socket thread creation failed"); + + g_socket_connected = 1; + d_msg_to(D_MSG_TO_SOCKET, 1); +} + +void d_msg_deregister_socket() +{ + d_msg_to(D_MSG_TO_SOCKET, 0); + g_socket_connected = 0; + + thread_delete(socket_thread); + + close(g_socket_fd); + g_socket_fd = -1; +} + +static void *THREAD_FUNC socket_main(thread_id id, void *data) +{ + int ret; + char *path = data; + + ret = socket_handler(path); + if (ret != 0) + { + d_error("Failed to initialize logger."); + d_error("Check file permission for `%s`", path); + } + + return NULL; +} + +static int socket_handler(const char *path) +{ + status_t rv; + int ret; + size_t nbytes; + ssize_t r; + int us; + fd_set readfd; + struct timeval timer_val; + struct sockaddr_un svaddr; + file_t *g_file = NULL; + char g_buffer[1024]; + + us = socket(AF_UNIX, SOCK_DGRAM, 0); + if (us < 0) + { + d_error("socket() failed. (%d:%s)", errno, strerror(errno)); + return -1; + } + memcpy(&svaddr, &g_socket_addr, sizeof(struct sockaddr_un)); + + ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr)); + if (ret != 0) + { + if (errno == EADDRINUSE) + { + ret = file_remove(svaddr.sun_path); + if (ret != 0) + { + d_error("unlink(`%s`) failed. (%d:%s)", + svaddr.sun_path, errno, strerror(errno)); + return -1; + } + ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr)); + if (ret != 0) + { + d_error("bind() failed 2. (%d:%s)", errno, strerror(errno)); + return -1; + } + } + else + { + d_error("bind() failed. (%d:%s)", errno, strerror(errno)); + return -1; + } + } + + rv = file_open(&g_file, path, + FILE_CREATE | FILE_WRITE| FILE_APPEND, + FILE_UREAD | FILE_UWRITE | FILE_GREAD); + if (rv != CORE_OK) + { + d_error("Cannot open log file '%s'", path); + close(us); + return -1; + } + + while (!thread_should_stop()) + { + timer_val.tv_sec = 0; + timer_val.tv_usec = 50000; + FD_ZERO(&readfd); + FD_SET(us, &readfd); + + r = select (us+1, &readfd, NULL, NULL, &timer_val); + if (r == -1) + { + if (errno == EINTR) + break; + d_error("select() error(%d: %s)", errno, strerror(errno)); + } + + if (r == 0) + continue; + + if (FD_ISSET(us, &readfd)) + { + r = read(us, g_buffer, sizeof(g_buffer)); + + if (r < 0) + { + if (errno == EINTR) + break; + d_error("read() failed. (%d:%s)", errno, strerror(errno)); + continue; + } + + if (r == 0) + continue; + + nbytes = r; + rv = file_write(g_file, g_buffer, &nbytes); + if (rv != CORE_OK || r != nbytes) + { + d_error("Cannot write %ld bytes to log file (%ld written)", + (long)r, (long)nbytes); + } + } + } + + file_close(g_file); + + close(us); + + file_remove(svaddr.sun_path); + + return 0; } void d_msg_register_console(int console_fd) @@ -83,10 +231,10 @@ void d_msg_to(int to, int on_off) g_msg_to | D_MSG_TO_SYSLOG : g_msg_to & ~D_MSG_TO_SYSLOG; break; - case D_MSG_TO_LOGD: + case D_MSG_TO_SOCKET: g_msg_to = on_off ? - g_msg_to | D_MSG_TO_LOGD : - g_msg_to & ~D_MSG_TO_LOGD; + g_msg_to | D_MSG_TO_SOCKET : + g_msg_to & ~D_MSG_TO_SOCKET; break; case D_MSG_TO_ALL: g_msg_to = on_off ? D_MSG_TO_ALL : 0; @@ -114,14 +262,14 @@ void d_log_set_level(int to, int level) case D_MSG_TO_SYSLOG: g_log_level_syslog = level; break; - case D_MSG_TO_LOGD: - g_log_level_logd = level; + case D_MSG_TO_SOCKET: + g_log_level_socket = level; break; case D_MSG_TO_ALL: g_log_level_console = level; g_log_level_stdout = level; g_log_level_syslog = level; - g_log_level_logd = level; + g_log_level_socket = level; break; default: break; @@ -138,8 +286,8 @@ int d_log_get_level(int to) return g_log_level_stdout; case D_MSG_TO_SYSLOG: return g_log_level_syslog; - case D_MSG_TO_LOGD: - return g_log_level_logd; + case D_MSG_TO_SOCKET: + return g_log_level_socket; default: break; } @@ -160,14 +308,14 @@ void d_log_full(int to) case D_MSG_TO_SYSLOG: g_log_level_syslog = D_LOG_LEVEL_FULL; break; - case D_MSG_TO_LOGD: - g_log_level_logd = D_LOG_LEVEL_FULL; + case D_MSG_TO_SOCKET: + g_log_level_socket = D_LOG_LEVEL_FULL; break; case D_MSG_TO_ALL: g_log_level_console = D_LOG_LEVEL_FULL; g_log_level_stdout = D_LOG_LEVEL_FULL; g_log_level_syslog = D_LOG_LEVEL_FULL; - g_log_level_logd = D_LOG_LEVEL_FULL; + g_log_level_socket = D_LOG_LEVEL_FULL; break; default: break; @@ -187,14 +335,14 @@ void d_log_off(int to) case D_MSG_TO_SYSLOG: g_log_level_syslog = D_LOG_LEVEL_NONE; break; - case D_MSG_TO_LOGD: - g_log_level_logd = D_LOG_LEVEL_NONE; + case D_MSG_TO_SOCKET: + g_log_level_socket = D_LOG_LEVEL_NONE; break; case D_MSG_TO_ALL: g_log_level_console = D_LOG_LEVEL_NONE; g_log_level_stdout = D_LOG_LEVEL_NONE; g_log_level_syslog = D_LOG_LEVEL_NONE; - g_log_level_logd = D_LOG_LEVEL_NONE; + g_log_level_socket = D_LOG_LEVEL_NONE; break; default: break; @@ -283,10 +431,10 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...) { syslog(LOG_DEBUG, "%s", fstr); } - if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD)) + if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET)) { - sendto(g_logd_fd, fstr, n, 0, - (struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr)); + sendto(g_socket_fd, fstr, n, 0, + (struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr)); } if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE)) { @@ -310,10 +458,10 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...) { syslog(LOG_DEBUG, "%s", fstr); } - if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD)) + if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET)) { - sendto(g_logd_fd, fstr, n, 0, - (struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr)); + sendto(g_socket_fd, fstr, n, 0, + (struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr)); } if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE)) { @@ -353,12 +501,12 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...) { syslog(LOG_INFO, "[%s\n", fstr + 13); } - if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD) && - lv <= g_log_level_logd) + if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET) && + lv <= g_log_level_socket) { fstr[n++] = '\n'; - sendto(g_logd_fd, fstr, n, 0, - (struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr)); + sendto(g_socket_fd, fstr, n, 0, + (struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr)); } if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE) && lv <= g_log_level_console) @@ -384,11 +532,11 @@ int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...) { syslog(LOG_CRIT, "[%s\n", fstr + 13); } - if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD)) + if (g_socket_connected && (g_msg_to & D_MSG_TO_SOCKET)) { fstr[n++] = '\n'; - sendto(g_logd_fd, fstr, n, 0, - (struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr)); + sendto(g_socket_fd, fstr, n, 0, + (struct sockaddr *)&g_socket_addr, sizeof(g_socket_addr)); } if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE)) { diff --git a/lib/core/src/unix/start.c b/lib/core/src/unix/start.c index 91d716478..e1484449a 100644 --- a/lib/core/src/unix/start.c +++ b/lib/core/src/unix/start.c @@ -51,7 +51,6 @@ status_t core_initialize(void) tlv_init(); tm_init(); msgq_init(); - d_msg_init(); signal_init(); return CORE_OK; @@ -65,7 +64,6 @@ void core_terminate(void) } /* Reverse ordered finalization */ - d_msg_final(); msgq_final(); tm_final(); tlv_final(); diff --git a/lib/logger/logger.c b/lib/logger/logger.c index dda8a45af..6cba99683 100644 --- a/lib/logger/logger.c +++ b/lib/logger/logger.c @@ -93,9 +93,7 @@ int logger_start(const char *path) int ret, count = 0; size_t nbytes; ssize_t r; -#if 0 /* deprecated by logrotate */ file_info_t finfo; -#endif int us; fd_set readfd; struct timeval timer_val; @@ -197,7 +195,6 @@ int logger_start(const char *path) (long)r, (long)nbytes); } -#if 0 /* Deprecated by logrotate */ if (count % FILE_CHECK_CYCLE == 0) { file_info_get(&finfo, FILE_INFO_SIZE, g_file); @@ -206,7 +203,6 @@ int logger_start(const char *path) log_file_backup(); } } -#endif count++; } diff --git a/src/Makefile.am b/src/Makefile.am index fdc0d0852..a6b364411 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,57 +10,46 @@ COMMON_INCLUDES = app.h libmme_la_SOURCES = $(COMMON_INCLUDES) mme.c $(COMMON_SOURCES) libmme_la_DEPENDENCIES = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/mme/libmme.la libmme_la_LIBADD = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/mme/libmme.la libhss_la_SOURCES = $(COMMON_INCLUDES) hss.c $(COMMON_SOURCES) libhss_la_DEPENDENCIES = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/hss/libhss.la libhss_la_LIBADD = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/hss/libhss.la libsgw_la_SOURCES = $(COMMON_INCLUDES) sgw.c $(COMMON_SOURCES) libsgw_la_DEPENDENCIES = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/sgw/libsgw.la libsgw_la_LIBADD = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/sgw/libsgw.la libpgw_la_SOURCES = $(COMMON_INCLUDES) pgw.c $(COMMON_SOURCES) libpgw_la_DEPENDENCIES = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/pgw/libpgw.la libpgw_la_LIBADD = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/pgw/libpgw.la libpcrf_la_SOURCES = $(COMMON_INCLUDES) pcrf.c $(COMMON_SOURCES) libpcrf_la_DEPENDENCIES = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/pcrf/libpcrf.la libpcrf_la_LIBADD = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/pcrf/libpcrf.la libepc_la_SOURCES = $(COMMON_INCLUDES) epc.c $(COMMON_SOURCES) libepc_la_DEPENDENCIES = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/mme/libmme.la \ $(top_srcdir)/src/hss/libhss.la \ $(top_srcdir)/src/sgw/libsgw.la \ @@ -68,7 +57,6 @@ libepc_la_DEPENDENCIES = \ $(top_srcdir)/src/pcrf/libpcrf.la libepc_la_LIBADD = \ $(top_srcdir)/lib/base/libbase.la \ - $(top_srcdir)/lib/logger/liblogger.la \ $(top_srcdir)/src/mme/libmme.la \ $(top_srcdir)/src/hss/libhss.la \ $(top_srcdir)/src/sgw/libsgw.la \ @@ -77,7 +65,6 @@ libepc_la_LIBADD = \ AM_CPPFLAGS = \ -I$(top_srcdir)/lib/core/include \ - -I$(top_srcdir)/lib/logger \ -I$(top_srcdir)/lib/base AM_CFLAGS = \ diff --git a/src/epc.c b/src/epc.c index 0bc359873..48ea8f166 100644 --- a/src/epc.c +++ b/src/epc.c @@ -41,7 +41,7 @@ status_t app_initialize(char *config_path, char *log_path) semaphore_create(&pcrf_sem1, 0); /* copied to PCRF/PGW/SGW/HSS process */ semaphore_create(&pcrf_sem2, 0); /* copied to PCRF/PGW/SGW/HSS process */ - if (context_self()->hidden.disable_pcrf == 0) + if (context_self()->node.disable_pcrf == 0) { pid = fork(); d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed"); @@ -85,7 +85,7 @@ status_t app_initialize(char *config_path, char *log_path) semaphore_create(&pgw_sem1, 0); /* copied to PGW/SGW/HSS process */ semaphore_create(&pgw_sem2, 0); /* copied to PGW/SGW/HSS process */ - if (context_self()->hidden.disable_pgw == 0) + if (context_self()->node.disable_pgw == 0) { pid = fork(); d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed"); @@ -133,7 +133,7 @@ status_t app_initialize(char *config_path, char *log_path) semaphore_create(&sgw_sem1, 0); /* copied to SGW/HSS process */ semaphore_create(&sgw_sem2, 0); /* copied to SGW/HSS process */ - if (context_self()->hidden.disable_sgw == 0) + if (context_self()->node.disable_sgw == 0) { pid = fork(); d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed"); @@ -183,7 +183,7 @@ status_t app_initialize(char *config_path, char *log_path) semaphore_create(&hss_sem1, 0); /* copied to HSS process */ semaphore_create(&hss_sem2, 0); /* copied to HSS process */ - if (context_self()->hidden.disable_hss == 0) + if (context_self()->node.disable_hss == 0) { pid = fork(); d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed"); @@ -247,7 +247,7 @@ void app_terminate(void) mme_terminate(); d_trace(1, "MME terminate...done\n"); - if (context_self()->hidden.disable_hss == 0) + if (context_self()->node.disable_hss == 0) { if (hss_sem2) semaphore_post(hss_sem2); if (hss_sem1) semaphore_wait(hss_sem1); @@ -255,7 +255,7 @@ void app_terminate(void) if (hss_sem1) semaphore_delete(hss_sem1); if (hss_sem2) semaphore_delete(hss_sem2); - if (context_self()->hidden.disable_sgw == 0) + if (context_self()->node.disable_sgw == 0) { if (sgw_sem2) semaphore_post(sgw_sem2); if (sgw_sem1) semaphore_wait(sgw_sem1); @@ -263,7 +263,7 @@ void app_terminate(void) if (sgw_sem1) semaphore_delete(sgw_sem1); if (sgw_sem2) semaphore_delete(sgw_sem2); - if (context_self()->hidden.disable_pgw == 0) + if (context_self()->node.disable_pgw == 0) { if (pgw_sem2) semaphore_post(pgw_sem2); if (pgw_sem1) semaphore_wait(pgw_sem1); @@ -271,7 +271,7 @@ void app_terminate(void) if (pgw_sem1) semaphore_delete(pgw_sem1); if (pgw_sem2) semaphore_delete(pgw_sem2); - if (context_self()->hidden.disable_pcrf == 0) + if (context_self()->node.disable_pcrf == 0) { if (pcrf_sem2) semaphore_post(pcrf_sem2); if (pcrf_sem1) semaphore_wait(pcrf_sem1); diff --git a/src/init.c b/src/init.c index 3ce940a7d..874910e71 100644 --- a/src/init.c +++ b/src/init.c @@ -5,15 +5,14 @@ #include "core_file.h" #include "context.h" -#include "logger.h" #include "app.h" #define DEFAULT_PID_DIR_PATH LOCALSTATE_DIR "run/" PACKAGE #define DEFAULT_CONFIG_FILE_PATH SYSCONF_DIR PACKAGE "/nextepc.conf" -static thread_id logger_thread = 0; -static void *THREAD_FUNC logger_main(thread_id id, void *data); +status_t app_socket_log_start(); +status_t app_socket_log_stop(); status_t app_will_initialize(char *config_path, char *log_path) { @@ -49,29 +48,14 @@ status_t app_will_initialize(char *config_path, char *log_path) status_t app_did_initialize(char *config_path, char *log_path) { - status_t rv; - - if (log_path) - context_self()->log_path = log_path; - - if (context_self()->log_path) - { - d_print(" Logging '%s'\n", context_self()->log_path); - rv = thread_create(&logger_thread, NULL, - logger_main, context_self()->log_path); - if (rv != CORE_OK) return rv; - } + app_socket_log_start(); return CORE_OK; } void app_will_terminate(void) { - if (logger_thread) - { - thread_delete(logger_thread); - } - + app_socket_log_stop(); } void app_did_terminate(void) @@ -84,37 +68,35 @@ void app_did_terminate(void) context_final(); } -static void *THREAD_FUNC logger_main(thread_id id, void *data) +status_t app_socket_log_start() { - int ret; - char *path = data; - - ret = logger_start(path); - if (ret != 0) + if (context_self()->log.socket.file && + context_self()->log.socket.unix_domain) { - d_error("Failed to initialize logger."); - d_error("Check file permission for `%s`", path); + d_msg_register_socket( + context_self()->log.socket.unix_domain, + context_self()->log.socket.file); + d_print(" Logging '%s'\n", context_self()->log.socket.file); } - return NULL; + return CORE_OK; +} + +status_t app_socket_log_stop() +{ + if (context_self()->log.socket.file && + context_self()->log.socket.unix_domain) + { + d_msg_deregister_socket(); + } + + return CORE_OK; } status_t logger_restart() { - status_t rv; - - if (logger_thread) - { - thread_delete(logger_thread); - - if (context_self()->log_path) - { - d_print(" Logging '%s'\n", context_self()->log_path); - rv = thread_create(&logger_thread, NULL, - logger_main, context_self()->log_path); - if (rv != CORE_OK) return rv; - } - } + app_socket_log_stop(); + app_socket_log_start(); return CORE_OK; } diff --git a/support/config/hss.conf.in b/support/config/hss.conf.in index 07a734bcb..658eb2549 100644 --- a/support/config/hss.conf.in +++ b/support/config/hss.conf.in @@ -1,15 +1,22 @@ { - DB_URI : "mongodb://localhost/nextepc", - LOG_PATH : "@LOCALSTATE_DIR@/log/nextepc/hss.log", - TRACE: + "DB_URI" : "mongodb://localhost/nextepc", + "LOG" : { - FD: 1, - OTHERS: 1, - } + "SOCKET" : + { + "FILE" : "@LOCALSTATE_DIR@/log/nextepc/hss.log", + "UNIX_DOMAIN" : "/tmp/nextepc-hssd.sock" + } + }, + "TRACE" : + { + "FD": 1, + "OTHERS": 1 + }, - HSS : + "HSS" : { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/hss.conf", + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/hss.conf" } } diff --git a/support/config/mme.conf.in b/support/config/mme.conf.in index 94ac91e0b..09431df7f 100644 --- a/support/config/mme.conf.in +++ b/support/config/mme.conf.in @@ -1,71 +1,78 @@ { - LOG_PATH : "@LOCALSTATE_DIR@/log/nextepc/mme.log", - TRACE: + "LOG" : { - S1AP: 1, - NAS: 1, - FD: 1, - GTP: 1, - OTHERS: 1, - } - - MME : - { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/mme.conf", - DEFAULT_PAGING_DRX : "v64", -#RELATIVE_CAPACITY : 255, - NETWORK : + "SOCKET" : { - S1AP_IPV4 : "127.76.0.1", - GTPC_IPV4: "127.76.0.1", + "FILE" : "@LOCALSTATE_DIR@/log/nextepc/mme.log", + "UNIX_DOMAIN" : "/tmp/nextepc-mmed.sock" } - GUMMEI: + }, + "TRACE" : + { + "S1AP": 1, + "NAS": 1, + "FD": 1, + "GTP": 1, + "OTHERS": 1 + }, + + "MME" : + { + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/mme.conf", + "DEFAULT_PAGING_DRX" : "v64", + "NETWORK" : + { + "S1AP_IPV4" : "127.76.0.1", + "GTPC_IPV4" : "127.76.0.1" + }, + "GUMMEI" : [ { - PLMN_ID : + "PLMN_ID" : { - MCC : "001", - MNC : "01" - } - MME_GID : 2, - MME_CODE : 1 + "MCC" : "001", + "MNC" : "01" + }, + "MME_GID" : 2, + "MME_CODE" : 1 } - ] - TAI: + ], + "TAI": [ { - PLMN_ID : + "PLMN_ID" : { - MCC: "001", - MNC: "01", - } - TAC: 12345 + "MCC": "001", + "MNC": "01" + }, + "TAC": 12345 + } + ], + "SECURITY" : + { + "INTEGRITY_ORDER" : [ "EIA1", "EIA2", "EIA0" ], + "CIPHERING_ORDER" : [ "EEA0", "EEA1", "EEA2" ] + } + }, + + "SGW" : + { + "NETWORK" : + [ + { + "GTPC_IPV4" : "127.76.0.2", + "GTPU_IPV4" : "127.76.0.2" } ] - SECURITY : + }, + + "PGW" : + { + "NETWORK" : { - INTEGRITY_ORDER : [ "EIA1", "EIA2", "EIA0" ] - CIPHERING_ORDER : [ "EEA0", "EEA1", "EEA2" ] + "GTPC_IPV4" : "127.76.0.3", + "GTPU_IPV4" : "127.76.0.3" } } - SGW : - { - NETWORK : - [ - { - GTPC_IPV4: "127.76.0.2", - GTPU_IPV4: "127.76.0.2", - } - ] - } - - PGW : - { - NETWORK : - { - GTPC_IPV4: "127.76.0.3", - GTPU_IPV4: "127.76.0.3" - } - } } diff --git a/support/config/nextepc.conf.in b/support/config/nextepc.conf.in index 3236c5326..d6003bb47 100644 --- a/support/config/nextepc.conf.in +++ b/support/config/nextepc.conf.in @@ -1,103 +1,109 @@ { - DB_URI : "mongodb://localhost/nextepc", - LOG_PATH : "@LOCALSTATE_DIR@/log/nextepc/nextepc.log", - TRACE: + "DB_URI" : "mongodb://localhost/nextepc", + "LOG" : { - S1AP: 1, - NAS: 1, - FD: 1, - GTP: 1, - OTHERS: 1, - } - NODE: - { - DISABLE_HSS: 0, - DISABLE_SGW: 0, - DISABLE_PGW: 0, - DISABLE_PCRF: 0 - } - - MME : - { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/mme.conf", - DEFAULT_PAGING_DRX : "v64", -#RELATIVE_CAPACITY : 255, - NETWORK : + "SOCKET" : { - S1AP_IPV4 : "127.76.0.1", - GTPC_IPV4: "127.76.0.1", + "FILE" : "@LOCALSTATE_DIR@/log/nextepc/nextepc.log", + "UNIX_DOMAIN" : "/tmp/nextepc-epcd.sock" } - GUMMEI: + }, + "TRACE" : + { + "S1AP": 1, + "NAS": 1, + "FD": 1, + "GTP": 1, + "OTHERS": 1 + }, + "NODE": + { + "DISABLE_HSS": 0, + "DISABLE_SGW": 0, + "DISABLE_PGW": 0, + "DISABLE_PCRF": 0 + }, + + "MME" : + { + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/mme.conf", + "DEFAULT_PAGING_DRX" : "v64", + "NETWORK" : + { + "S1AP_IPV4" : "127.76.0.1", + "GTPC_IPV4" : "127.76.0.1" + }, + "GUMMEI" : [ { - PLMN_ID : + "PLMN_ID" : { - MCC : "001", - MNC : "01" - } - MME_GID : 2, - MME_CODE : 1 + "MCC" : "001", + "MNC" : "01" + }, + "MME_GID" : 2, + "MME_CODE" : 1 } - ] - TAI: + ], + "TAI": [ { - PLMN_ID : + "PLMN_ID" : { - MCC: "001", - MNC: "01", - } - TAC: 12345 + "MCC": "001", + "MNC": "01" + }, + "TAC": 12345 } - ] - SECURITY : + ], + "SECURITY" : { - INTEGRITY_ORDER : [ "EIA1", "EIA2", "EIA0" ] - CIPHERING_ORDER : [ "EEA0", "EEA1", "EEA2" ] + "INTEGRITY_ORDER" : [ "EIA1", "EIA2", "EIA0" ], + "CIPHERING_ORDER" : [ "EEA0", "EEA1", "EEA2" ] } - } + }, - HSS : + "HSS" : { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/hss.conf", - } + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/hss.conf" + }, - SGW : + "SGW" : { - NETWORK : + "NETWORK" : [ { - GTPC_IPV4: "127.76.0.2", - GTPU_IPV4: "127.76.0.2", + "GTPC_IPV4" : "127.76.0.2", + "GTPU_IPV4" : "127.76.0.2" } ] - } + }, - PGW : + "PGW" : { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.conf", - NETWORK : + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.conf", + "NETWORK" : { - GTPC_IPV4: "127.76.0.3", - GTPU_IPV4: "127.76.0.3" - } - UE_NETWORK: + "GTPC_IPV4" : "127.76.0.3", + "GTPU_IPV4" : "127.76.0.3" + }, + "UE_NETWORK": [ { - IF_NAME: "pgwtun", - IPV4_POOL: "45.45.0.1/16" + "IF_NAME" : "pgwtun", + "IPV4_POOL" : "45.45.0.1/16" } - ] - DNS : + ], + "DNS" : { - PRIMARY_IPV4: "8.8.8.8", - SECONDARY_IPV4: "4.4.4.4" + "PRIMARY_IPV4" : "8.8.8.8", + "SECONDARY_IPV4" : "4.4.4.4" } - } + }, - PCRF : + "PCRF" : { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.conf", + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.conf" } } diff --git a/support/config/pcrf.conf.in b/support/config/pcrf.conf.in index b960e4b43..3c315c90d 100644 --- a/support/config/pcrf.conf.in +++ b/support/config/pcrf.conf.in @@ -1,15 +1,21 @@ { - DB_URI : "mongodb://localhost/nextepc", - LOG_PATH : "@LOCALSTATE_DIR@/log/nextepc/pcrf.log", - TRACE: + "DB_URI" : "mongodb://localhost/nextepc", + "LOG" : { - FD: 1, - OTHERS: 1, - } - - PCRF : + "SOCKET" : + { + "FILE" : "@LOCALSTATE_DIR@/log/nextepc/pcrf.log", + "UNIX_DOMAIN" : "/tmp/nextepc-pcrfd.sock" + } + }, + "TRACE" : { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.conf", + "FD": 1, + "OTHERS": 1 + }, + "PCRF" : + { + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pcrf.conf" } } diff --git a/support/config/pgw.conf.in b/support/config/pgw.conf.in index dc30e9a9d..5bbad725e 100644 --- a/support/config/pgw.conf.in +++ b/support/config/pgw.conf.in @@ -1,31 +1,39 @@ { - LOG_PATH : "@LOCALSTATE_DIR@/log/nextepc/pgw.log", - TRACE: + "LOG" : { - FD: 1, - GTP: 1, - OTHERS: 1, - } - - PGW : - { - FD_CONF_PATH : "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.conf", - NETWORK : + "SOCKET" : { - GTPC_IPV4: "127.76.0.3", - GTPU_IPV4: "127.76.0.3" + "FILE" : "@LOCALSTATE_DIR@/log/nextepc/pgw.log", + "UNIX_DOMAIN" : "/tmp/nextepc-pgwd.sock" } - UE_NETWORK: + }, + "TRACE" : + { + "FD": 1, + "GTP": 1, + "OTHERS": 1 + }, + + "PGW" : + { + "FD_CONF_PATH" : "@SYSCONF_DIR@/nextepc/freeDiameter/pgw.conf", + "NETWORK" : + { + "GTPC_IPV4" : "127.76.0.3", + "GTPU_IPV4" : "127.76.0.3" + }, + "UE_NETWORK": [ { - IF_NAME: "pgwtun", - IPV4_POOL: "45.45.0.1/16" + "IF_NAME" : "pgwtun", + "IPV4_POOL" : "45.45.0.1/16" } - ] - DNS : + ], + "DNS" : { - PRIMARY_IPV4: "8.8.8.8", - SECONDARY_IPV4: "4.4.4.4" + "PRIMARY_IPV4" : "8.8.8.8", + "SECONDARY_IPV4" : "4.4.4.4" } } + } diff --git a/support/config/sgw.conf.in b/support/config/sgw.conf.in index 870b1fa89..c55cdb30b 100644 --- a/support/config/sgw.conf.in +++ b/support/config/sgw.conf.in @@ -1,19 +1,27 @@ { - LOG_PATH : "@LOCALSTATE_DIR@/log/nextepc/sgw.log", - TRACE: + "LOG" : { - GTP: 1, - OTHERS: 1, - } + "SOCKET" : + { + "FILE" : "@LOCALSTATE_DIR@/log/nextepc/sgw.log", + "UNIX_DOMAIN" : "/tmp/nextepc-sgwd.sock" + } + }, + "TRACE" : + { + "GTP": 1, + "OTHERS": 1 + }, - SGW : + "SGW" : { - NETWORK : + "NETWORK" : [ { - GTPC_IPV4: "127.76.0.2", - GTPU_IPV4: "127.76.0.2", + "GTPC_IPV4" : "127.76.0.2", + "GTPU_IPV4" : "127.76.0.2" } ] } + }