/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface 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 OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see <http://www.gnu.org/licenses/>. Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. *******************************************************************************/ /***************************************************************************** Source MMEprocess.c Version 0.1 Date 2013/02/26 Product NAS stack Subsystem MME NAS main process Author Frederic Maurel Description Implements the Non-Access Stratum protocol for Evolved Packet system (EPS) running at the Network side. *****************************************************************************/ #include "commonDef.h" #include "nas_log.h" #include "nas_timer.h" #include "network_api.h" #include "nas_network.h" #include "nas_parser.h" #include <stdlib.h> // exit #include <poll.h> // poll #include <string.h> // memset #include <signal.h> // sigaction #include <pthread.h> /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ #define NAS_SLEEP_TIMEOUT 1000 /* 1 second */ static void *_nas_network_mngr(void *); static int _nas_set_signal_handler(int signal, void (handler)(int)); static void _nas_signal_handler(int signal); static void _nas_clean(int net_fd); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ /****************************************************************************/ int main(int argc, const char *argv[]) { /* * Get the command line options */ if (nas_parser_get_options (argc, argv) != RETURNok) { nas_parser_print_usage (FIRMWARE_VERSION); exit (EXIT_FAILURE); } /* * Initialize logging trace utility */ nas_log_init (nas_parser_get_trace_level ()); const char *nhost = nas_parser_get_network_host (); const char *nport = nas_parser_get_network_port (); LOG_TRACE (INFO, "MME-MAIN - %s -nhost %s -nport %s -trace 0x%x", argv[0], nhost, nport, nas_parser_get_trace_level ()); /* * Initialize the Network interface */ if (network_api_initialize (nhost, nport) != RETURNok) { LOG_TRACE (ERROR, "MME-MAIN - network_api_initialize() failed"); exit (EXIT_FAILURE); } int network_fd = network_api_get_fd (); /* * Initialize the NAS contexts */ nas_network_initialize (); /* * Initialize NAS timer handlers */ nas_timer_init (); /* * Set up signal handlers */ (void) _nas_set_signal_handler (SIGINT, _nas_signal_handler); (void) _nas_set_signal_handler (SIGTERM, _nas_signal_handler); pthread_attr_t attr; pthread_attr_init (&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); /* * Start thread use to manage the network connection endpoint */ pthread_t network_mngr; if (pthread_create (&network_mngr, &attr, _nas_network_mngr, &network_fd) != 0) { LOG_TRACE (ERROR, "MME-MAIN - " "Failed to create the network management thread"); network_api_close (network_fd); exit (EXIT_FAILURE); } pthread_attr_destroy (&attr); /* * Suspend execution of the main process until the network connection * endpoint is still active */ while (network_fd != -1) { poll (NULL, 0, NAS_SLEEP_TIMEOUT); network_fd = network_api_get_fd (); } /* Termination cleanup */ _nas_clean (network_fd); LOG_TRACE (WARNING, "MME-MAIN - NAS main process exited"); } /****************************************************************************/ /********************* L O C A L F U N C T I O N S *********************/ /****************************************************************************/ /**************************************************************************** ** ** ** Name: _nas_network_mngr() ** ** ** ** Description: Manages the connection endpoint use to communicate with ** ** the network sublayer ** ** ** ** Inputs: fd: The descriptor of the network connection ** ** endpoint ** ** Others: None ** ** ** ** Outputs: Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void *_nas_network_mngr(void *args) { LOG_FUNC_IN; int ret_code; int network_message_id; int bytes; int *fd = (int *) args; LOG_TRACE (INFO, "MME-MAIN - Network connection manager started (%d)", *fd); /* Network receiving loop */ while (TRUE) { /* Read the network data message */ bytes = network_api_read_data (*fd); if (bytes == RETURNerror) { /* Failed to read data from the network sublayer; * exit from the receiving loop */ LOG_TRACE (ERROR, "MME-MAIN - " "Failed to read data from the network sublayer"); break; } if (bytes == 0) { /* A signal was caught before any data were available */ continue; } /* Decode the network data message */ network_message_id = network_api_decode_data (bytes); if (network_message_id == RETURNerror) { /* Failed to decode data read from the network sublayer */ continue; } /* Process the network data message */ ret_code = nas_network_process_data (network_message_id, network_api_get_data ()); if (ret_code != RETURNok) { /* The network data message has not been successfully * processed */ LOG_TRACE (WARNING, "MME-MAIN - " "The network procedure call 0x%x failed", network_message_id); } } /* Close the connection to the network sublayer */LOG_TRACE (WARNING, "MME-MAIN - " "The network connection endpoint manager exited"); LOG_FUNC_RETURN(NULL); } /**************************************************************************** ** ** ** Name: _nas_set_signal_handler() ** ** ** ** Description: Set up a signal handler ** ** ** ** Inputs: signal: Signal number ** ** handler: Signal handler ** ** Others: None ** ** ** ** Outputs: Return: RETURNerror, RETURNok ** ** Others: None ** ** ** ***************************************************************************/ static int _nas_set_signal_handler(int signal, void (handler)(int)) { LOG_FUNC_IN; struct sigaction act; /* Initialize signal set */ (void) memset (&act, 0, sizeof(act)); (void) sigfillset (&act.sa_mask); (void) sigdelset (&act.sa_mask, SIGHUP); (void) sigdelset (&act.sa_mask, SIGINT); (void) sigdelset (&act.sa_mask, SIGTERM); (void) sigdelset (&act.sa_mask, SIGILL); (void) sigdelset (&act.sa_mask, SIGTRAP); (void) sigdelset (&act.sa_mask, SIGIOT); #ifndef LINUX (void) sigdelset (&act.sa_mask, SIGEMT); #endif (void) sigdelset (&act.sa_mask, SIGFPE); (void) sigdelset (&act.sa_mask, SIGBUS); (void) sigdelset (&act.sa_mask, SIGSEGV); (void) sigdelset (&act.sa_mask, SIGSYS); /* Initialize signal handler */ act.sa_handler = handler; if (sigaction (signal, &act, 0) < 0) { return RETURNerror; } LOG_TRACE (INFO, "MME-MAIN - Handler successfully set for signal %d", signal); LOG_FUNC_RETURN(RETURNok); } /**************************************************************************** ** ** ** Name: _nas_signal_handler() ** ** ** ** Description: Signal handler ** ** ** ** Inputs: signal: Signal number ** ** Others: None ** ** ** ** Outputs: Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void _nas_signal_handler(int signal) { LOG_FUNC_IN; LOG_TRACE (WARNING, "MME-MAIN - Signal %d received", signal); _nas_clean (network_api_get_fd ()); exit (EXIT_SUCCESS); LOG_FUNC_OUT ; } /**************************************************************************** ** ** ** Name: _nas_clean() ** ** ** ** Description: Performs termination cleanup ** ** ** ** Inputs: net_fd: Network's connection file descriptor ** ** Others: None ** ** ** ** Outputs: Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void _nas_clean(int net_fd) { LOG_FUNC_IN; LOG_TRACE (INFO, "MME-MAIN - Perform EMM and ESM cleanup"); nas_network_cleanup (); LOG_TRACE (INFO, "MME-MAIN - Closing network connection %d", net_fd); network_api_close (net_fd); LOG_FUNC_OUT ; }