aboutsummaryrefslogtreecommitdiffstats
path: root/tests/handover
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-01-28 03:04:16 +0100
committerHarald Welte <laforge@gnumonks.org>2018-03-16 18:49:47 +0000
commit3561bd48976dbee8dbd4659dad15be85a3e79ace (patch)
tree58c1f4453b00f66ac6d7f3d5b5082e149a8de766 /tests/handover
parent2cf46b97d3e5ec4b65cad7f7a2e18cc781558456 (diff)
introduce an osmo_fsm for gsm_subscriber_connection
In the current implementation of osmo-bsc, the subscriber connection is not handled (very) statefully. However, there is some state keeping in the code that handles the mgcp connection, but there are still to much loose ends which allow odd situations to happen, which then lead severe error situations (see also closes tags at the end) This commit adds a number of improvements to fix those problems. - Use an osmo-fsm to control the gsm_subscriber_connection state and make sure that certain operations can only take place at certain states (e.g let connection oriented SCCP traffic only pass when an SCCP connection actually exists. Remove the old osmo_bsc_mgcp.c code. Use the recently developed MGCP client FSM to handle the MGCP connections. Also make sure that stuff that already works does not break. This in particular refers to the internal handover capability and the respective unit-tests. See also OS#2823, OS#2768 and OS#2898 - Fix logic to permit assignment to a signalling channel. (OS#2762) - Introduce T993210 to release lchan + subscr_conn if MSC fails to respond The GSM specs don't have an explicit timer for this, so let's introdcue a custom timer (hence starting with 99). This timeout catches the following situation: * we send a SCCP CR with COMPL_L3_INFO from the MS to the MSC, * the MSC doesn't respond (e.g. SCCP routing failure, program down, ...) The MS is supposed to timeout with T3210, 3220 or 3230. But the BSC shouldn't trust the MS but have some timer on its own. SCCP would have a timer T(conn est), but that one is specified to be 1-2min and hence rather long. See also: OS#2775 - Terminate bsc_subscr_conn_fsm on SCCP N-DISC.ind from MSC If the MSC is disconnecting the SCCP channel, we must terminate the FSM which in turn will release all lchan's and other state. This makes TC_chan_rel_hard_rlsd pass, see also OS#2731 As a side-effect, this fixes TC_chan_act_ack_est_ind_refused(), where the MSC is answering with CREF to our CR/COMPL_L3. - Release subscriber connection on RLL RELEASE IND of SAPI0 on main DCCH The subscriber connection isn't really useful for anything after the SAPI0 main signalling link has been released. We could try to re-establish, but our best option is probably simply releasing the subscriber_conn and anything related to it. This will make TC_chan_rel_rll_rel_ind pass, see also OS#2730 This commit has been tested using the BSC_Tests TTCN3 testsuit and the following tests were passed: TC_chan_act_noreply TC_chan_act_ack_noest TC_chan_act_ack_est_ind_noreply TC_chan_act_ack_est_ind_refused TC_chan_act_nack TC_chan_exhaustion TC_ctrl TC_chan_rel_conn_fail TC_chan_rel_hard_clear TC_chan_rel_hard_rlsd TC_chan_rel_a_reset TC_rll_est_ind_inact_lchan TC_rll_est_ind_inval_sapi1 TC_rll_est_ind_inval_sapi3 TC_rll_est_ind_inval_sacch TC_assignment_cic_only TC_assignment_csd TC_assignment_ctm TC_assignment_fr_a5_0 TC_assignment_fr_a5_1_codec_missing TC_assignment_fr_a5_1 TC_assignment_fr_a5_3 TC_assignment_fr_a5_4 TC_paging_imsi_nochan TC_paging_tmsi_nochan TC_paging_tmsi_any TC_paging_tmsi_sdcch TC_paging_tmsi_tch_f TC_paging_tmsi_tch_hf TC_paging_imsi_nochan_cgi TC_paging_imsi_nochan_lac_ci TC_paging_imsi_nochan_ci TC_paging_imsi_nochan_lai TC_paging_imsi_nochan_lac TC_paging_imsi_nochan_all TC_paging_imsi_nochan_plmn_lac_rnc TC_paging_imsi_nochan_rnc TC_paging_imsi_nochan_lac_rnc TC_paging_imsi_nochan_lacs TC_paging_imsi_nochan_lacs_empty TC_paging_imsi_a_reset TC_paging_counter TC_rsl_drop_counter TC_classmark TC_unsol_ass_fail TC_unsol_ass_compl TC_unsol_ho_fail TC_err_82_short_msg TC_ho_int Authors: Harald Welte <laforge@gnumonks.org> Philipp Maier <pmaier@sysmocom.de> Neels Hofmeyr <neels@hofmeyr.de> Closes: OS#2730 Closes: OS#2731 Closes: OS#2762 Closes: OS#2768 Closes: OS#2775 Closes: OS#2823 Closes: OS#2898 Closes: OS#2936 Change-Id: I68286d26e2014048b054f39ef29c35fef420cc97
Diffstat (limited to 'tests/handover')
-rw-r--r--tests/handover/Makefile.am6
-rw-r--r--tests/handover/handover_test.c78
2 files changed, 81 insertions, 3 deletions
diff --git a/tests/handover/Makefile.am b/tests/handover/Makefile.am
index 7133fcddc..957bbeeb9 100644
--- a/tests/handover/Makefile.am
+++ b/tests/handover/Makefile.am
@@ -9,6 +9,8 @@ AM_CFLAGS = \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
+ $(LIBOSMOSIGTRAN_CFLAGS) \
+ $(LIBOSMOMGCPCLIENT_CFLAGS) \
$(NULL)
AM_LDFLAGS = \
@@ -28,7 +30,7 @@ handover_test_SOURCES = \
$(NULL)
handover_test_LDFLAGS =\
- -Wl,--wrap=abis_rsl_sendmsg \
+ -Wl,--wrap=abis_rsl_sendmsg,--wrap=mgcp_conn_modify,--wrap=mgcp_conn_delete\
$(NULL)
handover_test_LDADD = \
@@ -36,4 +38,6 @@ handover_test_LDADD = \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(LIBOSMOABIS_LIBS) \
+ $(LIBOSMOSIGTRAN_LIBS) \
+ $(LIBOSMOMGCPCLIENT_LIBS) \
$(NULL)
diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c
index bf7350c62..b03b65a6b 100644
--- a/tests/handover/handover_test.c
+++ b/tests/handover/handover_test.c
@@ -39,9 +39,59 @@
#include <osmocom/bsc/bss.h>
#include <osmocom/bsc/bsc_api.h>
#include <osmocom/bsc/osmo_bsc.h>
+#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
struct gsm_network *bsc_gsmnet;
+/* override, requires '-Wl,--wrap=mgcp_conn_modify'.
+ * Catch modification of an MGCP connection. */
+int __real_mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_conn_peer *conn_peer);
+int __wrap_mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_conn_peer *conn_peer)
+{
+ /* CAUTION HACK:
+ *
+ * The pointer fi is misused to pass a reference to GSCON FSM !
+ *
+ * This function is called from gscon_fsm_wait_ho_compl() from
+ * bsc_subscr_conn_fsm.c when GSCON_EV_HO_COMPL is dispatched to the
+ * GSCON FSM. By then, the GSCON FSM has already changed to the state
+ * ST_WAIT_MDCX_BTS_HO (see gscon_fsm_wait_mdcx_bts_ho()) and waits for
+ * GSCON_EV_MGW_MDCX_RESP_BTS. The signal GSCON_EV_MGW_MDCX_RESP_BTS
+ * is sent to this function using the parameter parent_evt. So we
+ * implicitly know the event that is needed to simulate a successful
+ * MGW negotiation to the GSCON FSM. All we need to do is to dispatch
+ * parent_evt back to the GSCON FSM in order to make it think that the
+ * MGW negotiation is done.
+ *
+ * Unfortunately, there is a problem with this test implementation.
+ * in order to simplfy the test we do not allocate any MGCP Client
+ * FSM but the GSCON FSM will call this function with the fi pointer
+ * pointing to the MGCP Client FSM. This means we get a nullpointer
+ * here and there is no way to distinguish which GSCON FSM called
+ * the function at all (normally we would know through the parent
+ * pointer).
+ *
+ * To get around this problem we populate the fi pointer with the
+ * reference to the GSCON FSM itsself, so we can know who called the
+ * function. This is a misuse of the pointer since it normally would
+ * hold an MGCP Client FSM instead of a GSCON FSM.
+ *
+ * See also note in function create_conn() */
+
+ osmo_fsm_inst_dispatch(fi, parent_evt, NULL);
+ return 0;
+}
+
+/* override, requires '-Wl,--wrap=mgcp_conn_delete'.
+ * Catch deletion of an MGCP connection. */
+int __real_mgcp_conn_delete(struct osmo_fsm_inst *fi);
+int __wrap_mgcp_conn_delete(struct osmo_fsm_inst *fi)
+{
+ /* Just do nothing and pretend that everything went well.
+ * We never have allocatec any MGCP connections. */
+ return 0;
+}
+
/* measurement report */
uint8_t meas_rep_ba = 0, meas_rep_valid = 1, meas_valid = 1, meas_multi_rep = 0;
@@ -186,7 +236,24 @@ static struct gsm_bts *create_bts(int arfcn)
void create_conn(struct gsm_lchan *lchan)
{
- lchan->conn = bsc_subscr_con_allocate(lchan);
+ struct gsm_subscriber_connection *conn;
+ conn = bsc_subscr_con_allocate(lchan->ts->trx->bts->network);
+
+ /* CAUTION HACK: When __real_mgcp_conn_modify() is called by the GSCON
+ * FSM, then we need to know the reference to caller FSM (GSCON FSM).
+ * Unfortunately the function __real_mgcp_conn_modify() is called with
+ * fi_bts, which is unpopulated in this setup. The real function would
+ * perform the communication with the MGW and then dispatch a signal
+ * back to the parent FSM. Since we do not have all that in this setup
+ * we populate the fi_bts pointer with a reference to the GSCON FSM in
+ * order to have it available later in __real_mgcp_conn_modify(). */
+ conn->user_plane.fi_bts = conn->fi;
+
+ lchan->conn = conn;
+ conn->lchan = lchan;
+ /* kick the FSM from INIT through to the ACTIVE state */
+ osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_CONN_REQ, NULL);
+ osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_CONN_CFM, NULL);
}
/* create lchan */
@@ -1256,6 +1323,11 @@ static const struct log_info_cat log_categories[] = {
.color = "\033[1;35m",
.enabled = 1, .loglevel = LOGL_DEBUG,
},
+ [DMSC] = {
+ .name = "DMSC",
+ .description = "Mobile Switching Center",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
};
const struct log_info log_info = {
@@ -1592,7 +1664,7 @@ int main(int argc, char **argv)
struct gsm_subscriber_connection *conn = lchan[i]->conn;
lchan[i]->conn = NULL;
conn->lchan = NULL;
- bsc_subscr_con_free(conn);
+ osmo_fsm_inst_term(conn->fi, OSMO_FSM_TERM_REGULAR, NULL);
lchan_free(lchan[i]);
}
@@ -1615,3 +1687,5 @@ void trau_mux_unmap() {}
void trau_mux_map_lchan() {}
void trau_recv_lchan() {}
void trau_send_frame() {}
+int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
+int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }