/* * Copyright (C) 2019 by Sukchan Lee * * This file is part of Open5GS. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ogs-sctp.h" #include "ogs-gtp.h" #include "mme-context.h" #include "mme-sm.h" #include "mme-event.h" #include "mme-timer.h" #include "mme-fd-path.h" #include "s1ap-path.h" #include "sgsap-path.h" #include "mme-gtp-path.h" #include "metrics.h" static ogs_thread_t *thread; static void mme_main(void *data); static int initialized = 0; int mme_initialize() { int rv; ogs_metrics_context_init(); ogs_gtp_context_init(OGS_MAX_NUM_OF_GTPU_RESOURCE); mme_context_init(); rv = ogs_gtp_xact_init(); if (rv != OGS_OK) return rv; rv = ogs_gtp_context_parse_config("mme", "sgwc"); if (rv != OGS_OK) return rv; rv = ogs_metrics_context_parse_config(); if (rv != OGS_OK) return rv; rv = mme_context_parse_config(); if (rv != OGS_OK) return rv; rv = mme_metrics_open(); if (rv != 0) return OGS_ERROR; rv = ogs_log_config_domain( ogs_app()->logger.domain, ogs_app()->logger.level); if (rv != OGS_OK) return rv; rv = mme_m_tmsi_pool_generate(); if (rv != OGS_OK) return rv; rv = mme_fd_init(); if (rv != OGS_OK) return OGS_ERROR; rv = mme_gtp_open(); if (rv != OGS_OK) return OGS_ERROR; rv = sgsap_open(); if (rv != OGS_OK) return OGS_ERROR; rv = s1ap_open(); if (rv != OGS_OK) return OGS_ERROR; thread = ogs_thread_create(mme_main, NULL); if (!thread) return OGS_ERROR; initialized = 1; return OGS_OK; } void mme_terminate(void) { if (!initialized) return; mme_event_term(); ogs_thread_destroy(thread); mme_gtp_close(); sgsap_close(); s1ap_close(); mme_metrics_close(); mme_fd_final(); mme_context_final(); ogs_gtp_context_final(); ogs_gtp_xact_final(); ogs_metrics_context_final(); } static void mme_main(void *data) { ogs_fsm_t mme_sm; int rv; ogs_fsm_create(&mme_sm, mme_state_initial, mme_state_final); ogs_fsm_init(&mme_sm, 0); for ( ;; ) { ogs_pollset_poll(ogs_app()->pollset, ogs_timer_mgr_next(ogs_app()->timer_mgr)); /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * * The reason is why ogs_timer_mgr_next() can get the corrent value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). * In this case, ogs_timer_mgr_expire() does not work * because 'if rv == OGS_DONE' statement is exiting and * not calling ogs_timer_mgr_expire(). */ ogs_timer_mgr_expire(ogs_app()->timer_mgr); for ( ;; ) { mme_event_t *e = NULL; rv = ogs_queue_trypop(ogs_app()->queue, (void**)&e); ogs_assert(rv != OGS_ERROR); if (rv == OGS_DONE) goto done; if (rv == OGS_RETRY) break; ogs_assert(e); ogs_fsm_dispatch(&mme_sm, e); mme_event_free(e); } } done: ogs_fsm_fini(&mme_sm, 0); ogs_fsm_delete(&mme_sm); }