bsc: properly clean up conn after each test

Make all tests clean up BSSAP conn and RSL link. Now all
f_verify_talloc_count() in f_shutdown_helper() should pass, verifying no
conn or bsc_subscr leaks.

Related: OS#5337
Change-Id: I9396efcabc085d2850244c6468b83c5f3a3ff3a2
diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index 34d3d03..fe6d1b2 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -1633,6 +1633,7 @@
 		}
 	[] BSSAP.receive { repeat; }
 	}
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -1711,7 +1712,7 @@
 
 /* Run everything required up to sending a caller-specified assignment command and expect response */
 function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
-runs on test_CT {
+runs on test_CT return DchanTuple {
 	var BSSAP_N_CONNECT_ind rx_c_ind;
 	var RSL_Message rx_rsl;
 	var DchanTuple dt;
@@ -1738,13 +1739,15 @@
 		}
 	[] BSSAP.receive { repeat; }
 	}
+	return dt;
 }
 testcase TC_assignment_csd() runs on test_CT {
 	var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
 	var PDU_BSSAP ass_cmd := f_gen_ass_req();
 	ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
 	//exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
-	f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
+	var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -1753,7 +1756,8 @@
 	var PDU_BSSAP ass_cmd := f_gen_ass_req();
 	ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
 	//exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
-	f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
+	var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -1983,6 +1987,8 @@
 		{name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
 	};
 	f_statsd_expect(expect);
+	BSSAP.receive(tr_BSSMAP_ClearRequest);
+	f_perform_clear();
 }
 testcase TC_stats_conn_fail() runs on test_CT {
 	var TestHdlrParams pars := f_gen_test_hdlr_pars();
@@ -2445,6 +2451,7 @@
 		/* Send MT message: BSSAP -> RSL */
 		f_mt_l3_transceive(RSL, link_id, dlci, l3);
 	}
+	f_perform_clear();
 }
 testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
 	var TestHdlrParams pars := f_gen_test_hdlr_pars();
@@ -3556,8 +3563,10 @@
 	/* Expevct a CR with a matching Paging response on the A-Interface */
 	T.start;
 	alt {
-	[] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) {
+	[] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
 		setverdict(pass);
+		dt.sccp_conn_id := rx_c_ind.connectionId;
+		BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
 		}
 	[] BSSAP.receive {
 		setverdict(fail, "Received unexpected message on A-Interface!");
@@ -3567,6 +3576,7 @@
 		}
 	}
 
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -3738,6 +3748,7 @@
 	exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
 
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 testcase TC_ciph_mode_a5_0() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -3826,6 +3837,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
 
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 testcase TC_assignment_aoip_tla_v6() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -3848,6 +3860,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
 
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 testcase TC_assignment_fr_a5_0() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -3921,6 +3934,7 @@
 	/* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
 
 	f_establish_fully(ass_cmd, exp_fail);
+	f_perform_clear();
 }
 testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -3952,6 +3966,7 @@
 
 	/* Start ciphering, expect Cipher Mode Reject */
 	f_cipher_mode(g_pars.encr, exp_fail := true);
+	f_perform_clear();
 }
 testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
 	var TestHdlrParams pars := f_gen_test_hdlr_pars();
@@ -3983,6 +3998,7 @@
 		{ name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
 	};
 	f_statsd_expect(expect);
+	f_perform_clear();
 }
 
 testcase TC_assignment_sign() runs on test_CT {
@@ -4125,6 +4141,10 @@
 type record of CodecListTest CodecListTests
 
 private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
+	f_assignment_codec(id);
+}
+
+private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
 	var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
 	var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
 
@@ -4179,6 +4199,10 @@
 			}
 		}
 	}
+
+	if (do_perform_clear) {
+		f_perform_clear();
+	}
 }
 
 private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
@@ -4195,6 +4219,7 @@
 	log("expecting ASS FAIL like this: ", exp_fail);
 
 	f_establish_fully(ass_cmd, exp_fail);
+	f_perform_clear();
 }
 
 const CounterNameVals counternames_bsc_bts_assignment := {
@@ -4708,6 +4733,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Allow FR only */
@@ -4720,6 +4746,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Allow HR only (expect assignment failure) */
@@ -4732,6 +4759,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
 	f_establish_fully(ass_cmd, exp_fail);
+	f_perform_clear();
 }
 
 /* Allow FR only (expect assignment failure) */
@@ -4744,6 +4772,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
 	f_establish_fully(ass_cmd, exp_fail);
+	f_perform_clear();
 }
 
 /* Allow FR and HR, but prefer FR */
@@ -4757,6 +4786,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
 	exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Allow FR and HR, but prefer HR */
@@ -4770,6 +4800,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
 	exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Allow FR and HR, but prefer FR */
@@ -4783,6 +4814,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
 	exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Allow FR and HR, but prefer HR */
@@ -4796,6 +4828,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
 	exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Request a HR channel while all FR channels are exhausted, this is expected
@@ -4921,6 +4954,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
 	exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Allow FR and HR, but prefer FR */
@@ -4934,6 +4968,7 @@
 	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
 	exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
 	f_establish_fully(ass_cmd, exp_compl);
+	f_perform_clear();
 }
 
 /* Request a HR (prefered) or alternatively a FR channel, it is expected that
@@ -4984,6 +5019,8 @@
 		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
 		}
 	}
+
+	f_perform_clear();
 }
 testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5046,6 +5083,7 @@
 		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
 		}
 	}
+	f_perform_clear();
 }
 testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5106,6 +5144,8 @@
 	f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
 	BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
 	setverdict(pass);
+
+	f_perform_clear();
 }
 testcase TC_classmark() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5133,6 +5173,8 @@
 	f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
 
 	setverdict(pass);
+
+	f_perform_clear();
 }
 testcase TC_common_id() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5171,6 +5213,7 @@
 private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
 	f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
 	f_bssap_expect_nothing();
+	f_perform_clear();
 }
 testcase TC_unsol_ass_fail() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5186,6 +5229,7 @@
 private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
 	f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
 	f_bssap_expect_nothing();
+	f_perform_clear();
 }
 testcase TC_unsol_ass_compl() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5201,6 +5245,7 @@
 private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
 	f_est_single_l3(ts_RRM_HandoverFailure('00'O));
 	f_bssap_expect_nothing();
+	f_perform_clear();
 }
 testcase TC_unsol_ho_fail() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5221,6 +5266,7 @@
 	/* send short message */
 	RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
 	f_bssap_expect_nothing();
+	f_perform_clear();
 }
 testcase TC_err_82_short_msg() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5243,6 +5289,7 @@
 	[] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
 	[] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
 	}
+	f_perform_clear();
 }
 testcase TC_err_84_unknown_msg() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5349,6 +5396,8 @@
 
 	f_chan_act_verify_tsc(chan_act, BTS_TSC[1]);
 
+	f_perform_clear(RSL1, RSL1_PROC);
+
 	f_sleep(0.5);
 }
 
@@ -5499,7 +5548,9 @@
 			RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
 			f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
 		}
-	[] BSSAP.receive(tr_BSSMAP_ClearComplete) {}
+	[] BSSAP.receive(tr_BSSMAP_ClearComplete) {
+			BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+		}
 	}
 
 	f_sleep(0.5);
@@ -5615,7 +5666,9 @@
 	[] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
 	[] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
 	[] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
-	[] BSSAP.receive(tr_BSSMAP_ClearComplete);
+	[] BSSAP.receive(tr_BSSMAP_ClearComplete) {
+			BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+		}
 	}
 	setverdict(pass);
 }
@@ -5722,6 +5775,7 @@
 
 	f_mo_l3_transceive();
 	f_sleep(1.0);
+	f_perform_clear();
 }
 testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5803,6 +5857,7 @@
 
 	setverdict(pass);
 	f_sleep(1.0);
+	f_perform_clear();
 }
 testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -5900,6 +5955,7 @@
 
 	f_expect_dlcx_conns();
 	BSSAP.receive(tr_BSSMAP_ClearComplete);
+	BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
 
 	setverdict(pass);
 	f_sleep(1.0);
@@ -6233,6 +6289,7 @@
 
 	f_expect_dlcx_conns();
 	BSSAP.receive(tr_BSSMAP_ClearComplete);
+	BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
 
 	setverdict(pass);
 	f_sleep(1.0);
@@ -6326,6 +6383,7 @@
 
 	f_expect_dlcx_conns();
 	BSSAP.receive(tr_BSSMAP_ClearComplete);
+	BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
 
 	f_sleep(1.0);
 }
@@ -6415,6 +6473,7 @@
 
 	f_expect_dlcx_conns();
 	BSSAP.receive(tr_BSSMAP_ClearComplete);
+	BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
 
 	f_sleep(1.0);
 }
@@ -6496,6 +6555,7 @@
 	};
 	f_expect_dlcx_conns();
 	BSSAP.receive(tr_BSSMAP_ClearComplete);
+	BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
 
 	f_sleep(1.0);
 }
@@ -6711,6 +6771,8 @@
 	f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
 			"handover any to arfcn 871 bsic 11",
 			true, expect_target_tsc := BTS_TSC[1]);
+
+	f_perform_clear();
 }
 testcase TC_ho_neighbor_config_1() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -6775,6 +6837,7 @@
 	f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
 			"handover any to arfcn 871 bsic 12",
 			false);
+	f_perform_clear();
 }
 testcase TC_ho_neighbor_config_2() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -6826,6 +6889,7 @@
 	f_probe_for_handover("3.b", "HO to bts 2 works, explicitly listed as neighbor; no ambiguity because bts 3 is not listed as neighbor",
 			"handover any to arfcn 871 bsic 12",
 			true, expect_target_tsc := BTS_TSC[2]);
+	f_perform_clear();
 }
 testcase TC_ho_neighbor_config_3() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -6880,6 +6944,7 @@
 	f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
 			"handover any to arfcn 123 bsic 45",
 			true, true);
+	f_perform_clear();
 }
 testcase TC_ho_neighbor_config_4() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -6930,6 +6995,7 @@
 	f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
 			"handover any to arfcn 871 bsic 12",
 			true, true);
+	f_perform_clear();
 }
 testcase TC_ho_neighbor_config_5() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -6973,6 +7039,7 @@
 	f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
 			"handover any to arfcn 871 bsic 12",
 			false);
+	f_perform_clear();
 }
 testcase TC_ho_neighbor_config_6() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -7017,6 +7084,7 @@
 	f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
 			"handover any to arfcn 123 bsic 45",
 			true, true);
+	f_perform_clear();
 }
 testcase TC_ho_neighbor_config_7() runs on test_CT {
 	var MSC_ConnHdlr vc_conn;
@@ -7478,9 +7546,11 @@
 
 	/* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
 	 * on CCCH+SDCCH4+CBCH) */
+	var DchanTuples sdcch_cleanup := {};
 	var integer i;
 	for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
 		dt := f_est_dchan('23'O, i, '00010203040506'O);
+		sdcch_cleanup := sdcch_cleanup & { dt };
 	}
 
 	/* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
@@ -7512,6 +7582,11 @@
 	f_sleep(1.0);
 	f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
 
+	/* Clean up SDCCH lchans */
+	for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
+		f_perform_clear_test_ct(sdcch_cleanup[i]);
+	}
+
 	/* clean up config */
 	f_ts_set_chcomb(0, 0, 6, "PDCH");
 
@@ -7534,7 +7609,7 @@
 	}
 	f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
 
-	f_init(1);
+	f_init(1, guard_timeout := 60.0);
 
 	/* The dyn TS want to activate PDCH mode, ACK that. */
 	var RslChannelNr chan_nr;
@@ -7548,15 +7623,21 @@
 	/* GSM 44.018 Table 9.1.8.2:
 	 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
 	 */
+	var DchanTuples chan_cleanup := {};
 	for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
-		f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
 	}
 
 	/* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
-	f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+	chan_cleanup := chan_cleanup & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
 	/* Also occupy the seven other SDCCH of the dyn TS */
 	for (i := 0; i < 7; i := i+1) {
-		f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
+	}
+
+	/* Clean up SDCCH lchans */
+	for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+		f_perform_clear_test_ct(chan_cleanup[i]);
 	}
 
 	/* clean up config */
@@ -7602,9 +7683,11 @@
 
 	/* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
 	 * on CCCH+SDCCH4+CBCH) */
+	var DchanTuples chan_cleanup := {};
 	var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
 	for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
 		dt := f_est_dchan(ra, i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { dt };
 	}
 
 	/* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
@@ -7636,6 +7719,11 @@
 	f_sleep(1.0);
 	f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
 
+	/* Clean up SDCCH lchans */
+	for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+		f_perform_clear_test_ct(chan_cleanup[i]);
+	}
+
 	/* clean up config */
 	f_ts_reset_chcomb(0);
 	/* TODO: clean up other channels? */
@@ -7672,9 +7760,11 @@
 
 	/* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
 	 * on CCCH+SDCCH4+CBCH) */
+	var DchanTuples chan_cleanup := {};
 	var integer i;
 	for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
 		dt := f_est_dchan('23'O, i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { dt };
 	}
 
 	/* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
@@ -7702,6 +7792,11 @@
 	 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
 	 */
 
+	/* Clean up SDCCH lchans */
+	for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+		f_perform_clear_test_ct(chan_cleanup[i]);
+	}
+
 	/* clean up config */
 	f_ts_set_chcomb(0, 0, 6, "PDCH");
 
@@ -7836,6 +7931,15 @@
 	deactivate(ack_rel_req);
 }
 
+private function f_perform_clear_test_ct(DchanTuple dt)
+	runs on test_CT
+{
+	/* Instruct BSC to clear channel */
+	var BssmapCause cause := 0;
+	BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+	f_exp_chan_rel_and_clear(dt, 0);
+}
+
 private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
                                     template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
 runs on MSC_ConnHdlr {
@@ -8578,6 +8682,7 @@
 	}
 
 	setverdict(pass);
+	f_perform_clear();
 }
 
 /* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
@@ -8600,6 +8705,8 @@
 		setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
 		}
 	}
+	BSSAP.receive(tr_BSSMAP_ClearRequest);
+	f_perform_clear();
 }
 
 /* EMERGENCY CALL situation #1, allowed globally and by BTS */
@@ -9087,6 +9194,8 @@
 			setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
 			continue;
 		}
+
+		f_perform_clear_test_ct(dt);
 	}
 
 	/* Give the IUT some time to release all channels */
@@ -9158,6 +9267,8 @@
 		setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
 		return;
 	}
+
+	f_perform_clear_test_ct(dt);
 }
 testcase TC_fh_params_handover_cmd() runs on test_CT {
 	var FHParamsTrx fhp := f_TC_fh_params_gen();
@@ -9899,6 +10010,8 @@
 		}
 	}
 	T.stop;
+
+	f_perform_clear();
 }
 
 /* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
@@ -9948,7 +10061,7 @@
 
 private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
 	/* First fully set up a speech lchan */
-	f_TC_assignment_codec(id);
+	f_assignment_codec(id, do_perform_clear := false);
 
 	/* Trigger re-assignment to another lchan */
 	var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
@@ -10246,6 +10359,8 @@
 
 	/* First send the Chan Act ACK */
 	var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
+	var DchanTuple dt;
+	dt.rsl_chan_nr := chan_nr;
 	var RSL_IE_Body chan_ident_ie;
 	if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
 		setverdict(fail, "RSL Channel Identification IE is absent");
@@ -10266,9 +10381,11 @@
 
 	var BSSAP_N_CONNECT_ind rx_c_ind;
 	BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+	dt.sccp_conn_id := rx_c_ind.connectionId;
 	BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
 
 	f_sleep(1.0);
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -10291,6 +10408,8 @@
 
 	chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
 	var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
+	var DchanTuple dt;
+	dt.rsl_chan_nr := chan_nr;
 	var RSL_IE_Body chan_ident_ie;
 	if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
 		setverdict(fail, "RSL Channel Identification IE is absent");
@@ -10311,9 +10430,11 @@
 
 	var BSSAP_N_CONNECT_ind rx_c_ind;
 	BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+	dt.sccp_conn_id := rx_c_ind.connectionId;
 	BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
 
 	f_sleep(1.0);
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -10336,6 +10457,8 @@
 
 	chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
 	var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
+	var DchanTuple dt;
+	dt.rsl_chan_nr := chan_nr;
 	var RSL_IE_Body chan_ident_ie;
 	if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
 		setverdict(fail, "RSL Channel Identification IE is absent");
@@ -10356,9 +10479,11 @@
 
 	var BSSAP_N_CONNECT_ind rx_c_ind;
 	BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+	dt.sccp_conn_id := rx_c_ind.connectionId;
 	BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
 
 	f_sleep(1.0);
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -10406,6 +10531,8 @@
 
 	/* Now activation as SDCCH8 */
 	chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
+	var DchanTuple dt;
+	dt.rsl_chan_nr := chan_nr;
 
 	chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
 	var RSL_IE_Body chan_ident_ie;
@@ -10428,9 +10555,11 @@
 
 	var BSSAP_N_CONNECT_ind rx_c_ind;
 	BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+	dt.sccp_conn_id := rx_c_ind.connectionId;
 	BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
 
 	f_sleep(1.0);
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -10483,6 +10612,8 @@
 
 	/* Now activation as SDCCH8 */
 	chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
+	var DchanTuple dt;
+	dt.rsl_chan_nr := chan_nr;
 
 	chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
 	var RSL_IE_Body chan_ident_ie;
@@ -10501,9 +10632,11 @@
 
 	var BSSAP_N_CONNECT_ind rx_c_ind;
 	BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+	dt.sccp_conn_id := rx_c_ind.connectionId;
 	BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
 
 	f_sleep(1.0);
+	f_perform_clear_test_ct(dt);
 	f_shutdown_helper();
 }
 
@@ -10607,6 +10740,8 @@
 	f_create_chan_and_exp();
 	/* we should now have a COMPL_L3 at the MSC */
 	BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
+	RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
+	f_perform_clear();
 	f_sleep(1.0);
 }
 testcase TC_cm_serv_rej() runs on test_CT {
@@ -10733,15 +10868,16 @@
 	var integer i;
 	var integer chreq_total, chreq_nochan;
 
-	f_init(1);
+	f_init(1, guard_timeout := 60.0);
 	f_sleep(1.0);
 
 	/* Exhaust all dedicated SDCCH lchans.
 	/* GSM 44.018 Table 9.1.8.2:
 	 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
 	 */
+	var DchanTuples chan_cleanup := {};
 	for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
-		f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
 	}
 
 	/* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
@@ -10751,13 +10887,18 @@
 
 	/* Also fill up all remaining (TCH) channels */
 	for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
-		f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
 	}
 
 	/* All TCH are now also occupied */
 	f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
 			"all_allocated:tch", "all_allocated:static_tch"});
 
+	/* Clean up SDCCH lchans */
+	for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+		f_perform_clear_test_ct(chan_cleanup[i]);
+	}
+
 	f_shutdown_helper();
 }
 
@@ -10784,8 +10925,9 @@
 	/* GSM 44.018 Table 9.1.8.2:
 	 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
 	 */
+	var DchanTuples chan_cleanup := {};
 	for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
-		f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
 	}
 
 	/* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
@@ -10807,7 +10949,7 @@
 
 	/* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
 	for (i := 0; i < 5; i := i+1) {
-		f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+		chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
 	}
 
 	/* All TCH lchans are now also occupied, both static and dynamic */
@@ -10841,6 +10983,11 @@
 	/* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
 	f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
 
+	/* Clean up SDCCH lchans */
+	for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+		f_perform_clear_test_ct(chan_cleanup[i]);
+	}
+
 	/* clean up config */
 	f_ts_reset_chcomb(0);