From 1dde661dd6653f21ddb003f203f8a23f201d68c9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 27 Jan 2012 14:20:24 +0100 Subject: osmo-bsc: Add configurable option to spawn + respawn osmo-bsc_mgcp If it is configured in the config file or on the VTY, osmo-bsc will fork+exec osmo-bsc_mgcp. Furthermore, if osmo-bsc_mgcp dies, osmo-bsc will re-spawn it. This also means that we can now send a SIGHUP to osmo-bsc_mgcp in the event of a Msc (re)connect, causing it to send RSIP, which in turn is required by certain call agents that forget to send a AUEP on startup to determine the endpoint state of the media gateway[s]. --- openbsc/src/osmo-bsc/osmo_bsc_main.c | 44 +++++++++++++++++++++++-- openbsc/src/osmo-bsc/osmo_bsc_msc.c | 5 +++ openbsc/src/osmo-bsc/osmo_bsc_vty.c | 62 ++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 3 deletions(-) (limited to 'openbsc/src/osmo-bsc') diff --git a/openbsc/src/osmo-bsc/osmo_bsc_main.c b/openbsc/src/osmo-bsc/osmo_bsc_main.c index 9a799c0c6..6997f3b28 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_main.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_main.c @@ -138,15 +138,44 @@ static struct vty_app_info vty_info = { .is_config_node = bsc_vty_is_config_node, }; +static int spawn_mgcp(void) +{ + pid_t pid; + struct osmo_msc_data *data = bsc_gsmnet->msc_data; + + if (!data->bsc_mgcp.path) { + LOGP(DMGCP, LOGL_NOTICE, + "Config file instructs us to not start osmo-bsc_mgcp!\n"); + return 0; + } + + pid = fork(); + if (pid == 0) { + execlp(data->bsc_mgcp.path, "osmo-bsc_mgcp", "-c", + data->bsc_mgcp.config_path, NULL); + /* only in case of error we ever end up here */ + fprintf(stderr, "Unable to exec() mgcp `%s`: %s\n", + data->bsc_mgcp.path, strerror(errno)); + exit(1); + } else { + data->bsc_mgcp.pid = pid; + return 0; + } +} + extern int bsc_shutdown_net(struct gsm_network *net); -static void signal_handler(int signal) +static void signal_handler(int signum) { - fprintf(stdout, "signal %u received\n", signal); + fprintf(stdout, "signal %u received\n", signum); - switch (signal) { + switch (signum) { case SIGINT: bsc_shutdown_net(bsc_gsmnet); osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL); + if (bsc_gsmnet->msc_data && bsc_gsmnet->msc_data->bsc_mgcp.pid) { + signal(SIGCHLD, SIG_IGN); + kill(bsc_gsmnet->msc_data->bsc_mgcp.pid, SIGTERM); + } sleep(3); exit(0); break; @@ -166,6 +195,12 @@ static void signal_handler(int signal) return; bsc_msc_lost(bsc_gsmnet->msc_data->msc_con); break; + case SIGCHLD: + /* bsc_mgcp seems to have died */ + /* sleep for some time to avoid fork bomb */ + sleep(1); + spawn_mgcp(); + break; default: break; } @@ -459,8 +494,11 @@ int main(int argc, char **argv) signal(SIGABRT, &signal_handler); signal(SIGUSR1, &signal_handler); signal(SIGUSR2, &signal_handler); + signal(SIGCHLD, &signal_handler); osmo_init_ignore_signals(); + spawn_mgcp(); + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c index 04cfb997d..68c469946 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -342,6 +343,10 @@ static void msc_connection_connected(struct bsc_msc_connection *con) data = (struct osmo_msc_data *) con->write_queue.bfd.data; msc_ping_timeout_cb(data); + /* notify bsc_mgcp to reset all end-points */ + if (data->bsc_mgcp.pid) + kill(data->bsc_mgcp.pid, SIGHUP); + sig.data = data; osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, &sig); } diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c index 0b1698e41..912d44646 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c @@ -18,6 +18,8 @@ * */ +#include + #include #include #include @@ -325,6 +327,61 @@ DEFUN(cfg_net_rf_socket, return CMD_SUCCESS; } +#define MGCP_STR "Configuration of the osmo-bsc_mgcp\n" + +DEFUN(cfg_net_msc_mgcp, cfg_net_msc_mgcp_cmd, + "bsc-mgcp executable PATH", MGCP_STR + "Set the filename / path of the osmo-bsc_mgcp executable.\n" + "filename / path of the osmo-bsc_mgcp executable\n") +{ + struct osmo_msc_data *data = osmo_msc_data(vty); + int equal = 0; + + if (data->bsc_mgcp.path && !strcmp(data->bsc_mgcp.path, argv[0])) + equal = 1; + + bsc_replace_string(data, &data->bsc_mgcp.path, argv[0]); + + if (equal) + return CMD_SUCCESS; + + if (data->bsc_mgcp.pid) { + kill(data->bsc_mgcp.pid, SIGTERM); + data->bsc_mgcp.pid = 0; + /* we will get SIGCHLD and re-spawn new path */ + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_net_msc_no_mgcp, cfg_net_msc_no_mgcp_cmd, + "no bsc-mgcp executable", NO_STR MGCP_STR + "Do not start osmo-bsc_mgcp from osmo-bsc\n") +{ + struct osmo_msc_data *data = osmo_msc_data(vty); + + talloc_free(data->bsc_mgcp.path); + data->bsc_mgcp.path = NULL; + + if (data->bsc_mgcp.pid) { + kill(data->bsc_mgcp.pid, SIGTERM); + data->bsc_mgcp.pid = 0; + /* SIGCHLD handler will not try to respawn, as path == NULL */ + } + return CMD_SUCCESS; +} + +DEFUN(cfg_net_msc_cfg_mgcp, cfg_net_msc_mgcp_cfg_cmd, + "bsc-mgcp config-file PATH", MGCP_STR + "Set the filename / path of the osmo-bsc_mgcp config file\n" + "filename / path of the osmo-bsc_mgcp config file\n") +{ + struct osmo_msc_data *data = osmo_msc_data(vty); + + bsc_replace_string(data, &data->bsc_mgcp.config_path, argv[0]); + return CMD_SUCCESS; +} + DEFUN(show_statistics, show_statistics_cmd, "show statistics", @@ -353,6 +410,11 @@ int bsc_vty_init_extra(void) install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd); install_element(MSC_NODE, &cfg_net_rf_socket_cmd); + /* FIXME: this should probably be a global MGCP node? */ + install_element(MSC_NODE, &cfg_net_msc_mgcp_cmd); + install_element(MSC_NODE, &cfg_net_msc_no_mgcp_cmd); + install_element(MSC_NODE, &cfg_net_msc_mgcp_cfg_cmd); + install_element_ve(&show_statistics_cmd); return 0; -- cgit v1.2.3