From 1b894022fd168d7b9a3e8cafaef1622c3a24885b Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Wed, 28 Aug 2013 10:16:54 +0200 Subject: [PATCH] bsc/ussd: Optionally send USSD message on MSC disconnection Send an USSD message on each MS connection if the connection to the MSC has been lost. Add a vty config command 'bsc-msc-loss-txt' in 'config-msc' to set the notification string and to enable the feature. Ticket: OW#957 --- openbsc/include/openbsc/osmo_msc_data.h | 3 ++ openbsc/src/osmo-bsc/osmo_bsc_sccp.c | 30 +++++++++++++++--- openbsc/src/osmo-bsc/osmo_bsc_vty.c | 35 +++++++++++++++++++++ openbsc/tests/vty_test_runner.py | 41 +++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/osmo_msc_data.h b/openbsc/include/openbsc/osmo_msc_data.h index ba93a089d..86b4a8455 100644 --- a/openbsc/include/openbsc/osmo_msc_data.h +++ b/openbsc/include/openbsc/osmo_msc_data.h @@ -83,6 +83,9 @@ struct osmo_msc_data { struct osmo_wqueue mgcp_agent; int nr; + + /* ussd msc connection lost text */ + char *ussd_msc_lost_txt; }; /* diff --git a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c index 3533d6df0..ad554e82a 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c @@ -262,13 +262,35 @@ int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp) return 0; } -static void bsc_close_connections(struct bsc_msc_connection *msc_con) +static void bsc_notify_msc_lost(struct osmo_bsc_sccp_con *con) +{ + struct gsm_subscriber_connection *conn = con->conn; + + /* send USSD notification if string configured and con->data is set */ + if (!conn) + return; + + /* check for config string */ + if (!con->msc->ussd_msc_lost_txt) + return; + if (con->msc->ussd_msc_lost_txt[0] == '\0') + return; + + /* send USSD notification */ + gsm0480_send_ussdNotify(conn, 1, conn->sccp_con->msc->ussd_welcome_txt); + gsm0480_send_releaseComplete(conn); +} + +static void bsc_notify_and_close_conns(struct bsc_msc_connection *msc_con) { struct osmo_bsc_sccp_con *con, *tmp; llist_for_each_entry_safe(con, tmp, &active_connections, entry) { - if (con->msc->msc_con == msc_con) - bsc_sccp_force_free(con); + if (con->msc->msc_con != msc_con) + continue; + + bsc_notify_msc_lost(con); + bsc_sccp_force_free(con); } } @@ -282,7 +304,7 @@ static int handle_msc_signal(unsigned int subsys, unsigned int signal, msc = signal_data; if (signal == S_MSC_LOST) - bsc_close_connections(msc->data->msc_con); + bsc_notify_and_close_conns(msc->data->msc_con); return 0; } diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c index 49ae665a6..501d9f51b 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c @@ -114,6 +114,11 @@ static void write_msc(struct vty *vty, struct osmo_msc_data *msc) if (msc->ussd_welcome_txt) vty_out(vty, " bsc-welcome-text %s%s", msc->ussd_welcome_txt, VTY_NEWLINE); + if (msc->ussd_msc_lost_txt && msc->ussd_msc_lost_txt[0]) + vty_out(vty, " bsc-msc-lost-text %s%s", msc->ussd_msc_lost_txt, VTY_NEWLINE); + else + vty_out(vty, " no bsc-msc-lost-text%s", VTY_NEWLINE); + if (msc->audio_length != 0) { int i; @@ -368,6 +373,34 @@ DEFUN(cfg_net_msc_welcome_ussd, return CMD_SUCCESS; } +DEFUN(cfg_net_msc_lost_ussd, + cfg_net_msc_lost_ussd_cmd, + "bsc-msc-lost-text .TEXT", + "Set the USSD notification to be sent on MSC connection loss\n" "Text to be sent\n") +{ + struct osmo_msc_data *data = osmo_msc_data(vty); + char *str = argv_concat(argv, argc, 0); + if (!str) + return CMD_WARNING; + + bsc_replace_string(osmo_bsc_data(vty), &data->ussd_msc_lost_txt, str); + talloc_free(str); + return CMD_SUCCESS; +} + +DEFUN(cfg_net_msc_no_lost_ussd, + cfg_net_msc_no_lost_ussd_cmd, + "no bsc-msc-lost-text", + NO_STR "Clear the USSD notification to be sent on MSC connection loss\n") +{ + struct osmo_msc_data *data = osmo_msc_data(vty); + + talloc_free(data->ussd_msc_lost_txt); + data->ussd_msc_lost_txt = 0; + + return CMD_SUCCESS; +} + DEFUN(cfg_net_msc_type, cfg_net_msc_type_cmd, "type (normal|local)", @@ -579,6 +612,8 @@ int bsc_vty_init_extra(void) install_element(MSC_NODE, &cfg_net_msc_ping_time_cmd); install_element(MSC_NODE, &cfg_net_msc_pong_time_cmd); install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd); + install_element(MSC_NODE, &cfg_net_msc_lost_ussd_cmd); + install_element(MSC_NODE, &cfg_net_msc_no_lost_ussd_cmd); install_element(MSC_NODE, &cfg_net_msc_type_cmd); install_element(MSC_NODE, &cfg_net_msc_emerg_cmd); install_element(MSC_NODE, &cfg_net_msc_local_prefix_cmd); diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index a7a7b3fb8..fd200c850 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -88,6 +88,39 @@ class TestVTYNITB(TestVTYBase): self.assertEquals(res.find('periodic location update 60'), -1) self.assert_(res.find('no periodic location update') > 0) +class TestVTYBSC(TestVTYBase): + + def vty_command(self): + return ["./src/osmo-bsc/osmo-bsc", "-c", + "doc/examples/osmo-bsc/osmo-bsc.cfg"] + + def vty_app(self): + return (4242, "./src/osmo-bsc/osmo-bsc", "OsmoBSC", "bsc") + + def testUssdNotifications(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("msc") + + # Test invalid input + self.vty.verify("bsc-msc-lost-text", ['% Command incomplete.']) + + # Enable USSD notifications + self.vty.verify("bsc-msc-lost-text MSC disconnected", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find('bsc-msc-lost-text MSC disconnected') > 0) + self.assertEquals(res.find('no bsc-msc-lost-text'), -1) + + # Now disable it.. + self.vty.verify("no bsc-msc-lost-text", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assertEquals(res.find('bsc-msc-lost-text MSC disconnected'), -1) + self.assert_(res.find('no bsc-msc-lost-text') > 0) + class TestVTYNAT(TestVTYBase): def vty_command(self): @@ -189,6 +222,13 @@ def add_nat_test(suite, workdir): test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT) suite.addTest(test) +def add_bsc_test(suite, workdir): + if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")): + print("Skipping the BSC test") + return + test = unittest.TestLoader().loadTestsFromTestCase(TestVTYBSC) + suite.addTest(test) + if __name__ == '__main__': import argparse import sys @@ -219,6 +259,7 @@ if __name__ == '__main__': print "Running tests for specific VTY commands" suite = unittest.TestSuite() suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestVTYNITB)) + add_bsc_test(suite, workdir) add_nat_test(suite, workdir) res = unittest.TextTestRunner(verbosity=verbose_level).run(suite) sys.exit(len(res.errors) + len(res.failures))