Change in osmo-ttcn3-hacks[master]: add bsc/BSC_Tests_VAMOS.ttcn

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

neels gerrit-no-reply at lists.osmocom.org
Tue May 25 21:46:43 UTC 2021


neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/24411 )


Change subject: add bsc/BSC_Tests_VAMOS.ttcn
......................................................................

add bsc/BSC_Tests_VAMOS.ttcn

BSC_Tests_VAMOS.ttcn is separate from BSC_Tests.ttcn in order to
instruct osmo-bts-omldummy to pass BTS_FEAT_VAMOS == true in the OML BTS
attributes.

Add tests:
TC_mode_modify_to_vamos()
TC_chan_act_to_vamos()
TC_assign_to_secondary_lchan()
TC_vamos_multiplex_tch_f_tch_f()

Change-Id: I2c504099163a30ea102cbd26d3615ca2e5ce1e64
---
A bsc/BSC_Tests_VAMOS.ttcn
1 file changed, 1,435 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/11/24411/1

diff --git a/bsc/BSC_Tests_VAMOS.ttcn b/bsc/BSC_Tests_VAMOS.ttcn
new file mode 100644
index 0000000..ac95827
--- /dev/null
+++ b/bsc/BSC_Tests_VAMOS.ttcn
@@ -0,0 +1,1435 @@
+module BSC_Tests_VAMOS {
+
+/* Integration Tests for OsmoBSC
+ * (C) 2017-2018 by Harald Welte <laforge at gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
+ * well as the MSC. See README for more details.
+ *
+ * There are test cases that run in so-called 'handler mode' and test cases
+ * that run directly on top of the BSSAP and RSL CodecPorts.  The "handler mode"
+ * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
+ * and/or RSL channels and are hence suitable for higher-level test cases, while
+ * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
+ * level testing.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from GSM_Types all;
+import from IPL4asp_Types all;
+
+import from BSSAP_Types all;
+import from RAN_Adapter all;
+import from BSSAP_LE_Adapter all;
+import from BSSAP_LE_CodecPort all;
+import from BSSAP_LE_Types all;
+import from BSSLAP_Types all;
+import from BSSAP_CodecPort all;
+import from BSSMAP_Templates all;
+import from IPA_Emulation all;
+import from IPA_CodecPort all;
+import from IPA_Types all;
+import from IPA_Testing all;
+import from RSL_Types all;
+import from RSL_Emulation all;
+import from MGCP_Emulation all;
+import from MGCP_Templates all;
+import from MGCP_Types all;
+import from MGCP_CodecPort all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from MobileL3_CommonIE_Types all;
+import from MobileL3_Types all;
+import from MobileL3_RRM_Types all;
+import from L3_Templates all;
+import from GSM_RR_Types all;
+
+import from SCCP_Templates all;
+import from BSSMAP_Templates all;
+import from BSSMAP_LE_Templates all;
+
+import from SCCPasp_Types all;
+
+import from GSM_SystemInformation all;
+import from GSM_RestOctets all;
+import from TCCConversion_Functions all;
+
+import from RAN_Emulation all;
+import from MSC_ConnectionHandler all;
+
+import from Native_Functions all;
+
+const integer NUM_BTS := 3;
+const integer NUM_MSC := 3;
+
+/* per-BTS state which we keep */
+type record BTS_State {
+	/* component reference to the IPA_Client component used for RSL */
+	IPA_Client rsl
+}
+
+/* Set of all System Information received during one RSL port's startup.
+ * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
+ * broadcast that SI type. That will be reflected as 'omit' here.
+ */
+type record SystemInformationConfig {
+	SystemInformationType1 si1 optional,
+	SystemInformationType2 si2 optional,
+	SystemInformationType2bis si2bis optional,
+	SystemInformationType2ter si2ter optional,
+	SI2quaterRestOctetsList si2quater optional,
+	SystemInformationType3 si3 optional,
+	SystemInformationType4 si4 optional,
+	SystemInformationType13 si13 optional,
+	SystemInformationType5 si5 optional,
+	SystemInformationType5bis si5bis optional,
+	SystemInformationType5ter si5ter optional,
+	SystemInformationType6 si6 optional
+};
+
+const SystemInformationConfig SystemInformationConfig_omit := {
+	si1 := omit,
+	si2 := omit,
+	si2bis := omit,
+	si2ter := omit,
+	si2quater := omit,
+	si3 := omit,
+	si4 := omit,
+	si13 := omit,
+	si5 := omit,
+	si5bis := omit,
+	si5ter := omit,
+	si6 := omit
+};
+
+/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests_VAMOS.ttcn */
+template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
+						    template uint3_t meas_bw := 3)
+:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
+		      meas_bw_presence := '1'B,
+		      meas_bw := meas_bw);
+
+/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests_VAMOS.ttcn */
+template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
+								template uint3_t prio := 3,
+								template (present) uint5_t thresh_high := 20,
+								template uint5_t thresh_low := 10,
+								template uint5_t qrxlevmin := 22)
+:= tr_EUTRAN_NeighbourCells(
+	cell_desc_list := cell_desc_list,
+	prio_presence := '1'B,
+	prio := prio,
+	thresh_high := thresh_high,
+	thresh_low_presence := '1'B,
+	thresh_low := thresh_low,
+	qrxlevmin_presence := '1'B,
+	qrxlevmin := qrxlevmin);
+
+template SystemInformationConfig SystemInformationConfig_default := {
+	si1 := {
+	    cell_chan_desc := '8FB38000000000000000000000000000'O,
+	    rach_control := {
+		max_retrans := RACH_MAX_RETRANS_7,
+		tx_integer := '1001'B,
+		cell_barr_access := false,
+		re_not_allowed := true,
+		acc := '0000010000000000'B
+	    },
+	    rest_octets := ?
+	},
+	si2 := {
+	    bcch_freq_list := '00000000000000000000000000000000'O,
+	    ncc_permitted := '11111111'B,
+	    rach_control := {
+		max_retrans := RACH_MAX_RETRANS_7,
+		tx_integer := '1001'B,
+		cell_barr_access := false,
+		re_not_allowed := true,
+		acc := '0000010000000000'B
+	    }
+	},
+	si2bis := omit,
+	si2ter := {
+	    extd_bcch_freq_list := '8E320000000000000000000000000800'O,
+	    rest_octets := ?
+	},
+	si2quater := {
+		tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
+	},
+	si3 := {
+	    cell_id := 0,
+	    lai := {
+		mcc_mnc := '001F01'H,
+		lac := 1
+	    },
+	    ctrl_chan_desc := {
+		msc_r99 := true,
+		att := true,
+		bs_ag_blks_res := 1,
+		ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
+		si22ind := false,
+		cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
+		spare := '00'B,
+		bs_pa_mfrms := 3,
+		t3212 := 30
+	    },
+	    cell_options := {
+		dn_ind := false,
+		pwrc := false,
+		dtx := MS_SHALL_USE_UL_DTX,
+		radio_link_tout_div4 := 7
+	    },
+	    cell_sel_par := {
+		cell_resel_hyst_2dB := 2,
+		ms_txpwr_max_cch := 7,
+		acs := '0'B,
+		neci := true,
+		rxlev_access_min := 0
+	    },
+	    rach_control := {
+		max_retrans := RACH_MAX_RETRANS_7,
+		tx_integer := '1001'B,
+		cell_barr_access := false,
+		re_not_allowed := true,
+		acc := '0000010000000000'B
+	    },
+	    rest_octets := {
+		sel_params := {
+		    presence := '0'B,
+		    params := omit
+		},
+		pwr_offset := {
+		    presence := '0'B,
+		    offset := omit
+		},
+		si_2ter_ind := '1'B,
+		early_cm_ind := '0'B,
+		sched_where := {
+		    presence := '0'B,
+		    where := omit
+		},
+		gprs_ind := {
+		    presence := '1'B,
+		    ind := {
+			ra_colour := 0,
+			si13_pos := '0'B
+		    }
+		},
+		umts_early_cm_ind := '1'B,
+		si2_quater_ind := {
+		    presence := '1'B,
+		    ind := '0'B
+		},
+		iu_mode_ind := omit,
+		si21_ind := {
+		    presence := '0'B,
+		    pos := omit
+		}
+	    }
+	},
+	si4 := {
+	    lai := {
+		mcc_mnc := '001F01'H,
+		lac := 1
+	    },
+	    cell_sel_par := {
+		cell_resel_hyst_2dB := 2,
+		ms_txpwr_max_cch := 7,
+		acs := '0'B,
+		neci := true,
+		rxlev_access_min := 0
+	    },
+	    rach_control := {
+		max_retrans := RACH_MAX_RETRANS_7,
+		tx_integer := '1001'B,
+		cell_barr_access := false,
+		re_not_allowed := true,
+		acc := '0000010000000000'B
+	    },
+	    cbch_chan_desc := {
+		iei := '64'O,
+		v := {
+		    chan_nr := {
+			u := {
+			sdcch4 := {
+			    tag := '001'B,
+			    sub_chan := 2
+			}
+			},
+			tn := 0
+		    },
+		    tsc := 2,
+		    h := false,
+		    arfcn := 871,
+		    maio_hsn := omit
+		}
+	    },
+	    cbch_mobile_alloc := omit,
+	    rest_octets := {
+		sel_params := {
+		    presence := '0'B,
+		    params := omit
+		},
+		pwr_offset := {
+		    presence := '0'B,
+		    offset := omit
+		},
+		gprs_ind := {
+		    presence := '1'B,
+		    ind := {
+			ra_colour := 0,
+			si13_pos := '0'B
+		    }
+		},
+		s_presence := '0'B,
+		s := omit
+	    }
+	},
+	si13 := {
+		rest_octets := {
+			presence := '1'B,
+			bcch_change_mark := ?,
+			si_change_field := '0000'B,
+			presence2 := '0'B,
+			si13_change_mark := omit,
+			gprs_ma := omit,
+			zero := '0'B, /* PBCCH not present in cell */
+			rac := 0,
+			spgc_ccch_sup := '0'B,
+			priority_access_thr := '110'B,
+			network_control_order := '00'B,
+			gprs_cell_opts := {
+				nmo := '01'B,
+				t3168 := '011'B,
+				t3192 := '010'B,
+				drx_timer_max := '011'B,
+				access_burst_type := '0'B,
+				control_ack_type := '1'B,
+				bs_cv_max := 15,
+				pan_presence := '1'B,
+				pan_dec  := 1,
+				pan_inc  := 1,
+				pan_max  := '111'B,
+				ext_info_presence := ?,
+				ext_info_length := *,
+				ext_info := *
+			},
+			gprs_pwr_ctrl_params := {
+				alpha := 0,
+				t_avg_w := '10000'B,
+				t_avg_t := '10000'B,
+				pc_meas_chan := '0'B,
+				n_avg_i := '1000'B
+			}
+		}
+	},
+	si5 := {
+	    bcch_freq_list := '10000000000000000000000000000000'O
+	},
+	si5bis := omit,
+	si5ter := {
+	    extd_bcch_freq_list := '9E050020000000000000000000000000'O
+	},
+	si6 := {
+	    cell_id := 0,
+	    lai := {
+		mcc_mnc := '001F01'H,
+		lac := 1
+	    },
+	    cell_options := {
+		dtx_ext := '1'B,
+		pwrc := false,
+		dtx := '01'B,
+		radio_link_timeout := '0111'B
+	    },
+	    ncc_permitted := '11111111'B,
+	    rest_octets := ?
+	}
+    };
+
+
+/* List of all the System Information received on all RSL ports */
+type record of SystemInformationConfig SystemInformationConfig_list;
+
+function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
+{
+	var RSL_IE_Body sysinfo_type_ie;
+	var RSL_IE_SysinfoType si_type;
+	var octetstring data;
+
+	if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
+		setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
+		mtc.stop;
+	}
+	si_type := sysinfo_type_ie.sysinfo_type;
+
+	if (rsl.msg_type == RSL_MT_BCCH_INFO) {
+		var RSL_IE_Body bcch_ie;
+		if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
+			data := bcch_ie.other.payload;
+		}
+	} else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
+		var RSL_IE_Body l3_ie;
+		if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
+			data := l3_ie.l3_info.payload;
+		}
+	} else {
+		setverdict(fail, "Don't understand this System Information message");
+		mtc.stop;
+	}
+
+	var boolean handled := false;
+
+	if (rsl.msg_type == RSL_MT_BCCH_INFO) {
+		handled := true;
+
+		if (si_type == RSL_SYSTEM_INFO_1) {
+			if (not isbound(data)) {
+				si.si1 := omit;
+			} else {
+				si.si1 := dec_SystemInformation(data).payload.si1;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_2) {
+			if (not isbound(data)) {
+				si.si2 := omit;
+			} else {
+				si.si2 := dec_SystemInformation(data).payload.si2;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_2bis) {
+			if (not isbound(data)) {
+				si.si2bis := omit;
+			} else {
+				si.si2bis := dec_SystemInformation(data).payload.si2bis;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_2ter) {
+			if (not isbound(data)) {
+				si.si2ter := omit;
+			} else {
+				si.si2ter := dec_SystemInformation(data).payload.si2ter;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_2quater) {
+			if (not isbound(data)) {
+				si.si2quater := {};
+			} else {
+				var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
+				/* this is a *record* of SI2quaterRestOctets! (multiplexed) */
+				si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_3) {
+			if (not isbound(data)) {
+				si.si3 := omit;
+			} else {
+				si.si3 := dec_SystemInformation(data).payload.si3;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_4) {
+			if (not isbound(data)) {
+				si.si4 := omit;
+			} else {
+				si.si4 := dec_SystemInformation(data).payload.si4;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_13) {
+			if (not isbound(data)) {
+				si.si13 := omit;
+			} else {
+				si.si13 := dec_SystemInformation(data).payload.si13;
+			}
+		} else {
+			handled := false;
+		}
+	} else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
+		handled := true;
+
+		if (si_type == RSL_SYSTEM_INFO_5) {
+			if (not isbound(data)) {
+				si.si5 := omit;
+			} else {
+				si.si5 := dec_SystemInformation(data).payload.si5;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_5bis) {
+			if (not isbound(data)) {
+				si.si5bis := omit;
+			} else {
+				si.si5bis := dec_SystemInformation(data).payload.si5bis;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_5ter) {
+			if (not isbound(data)) {
+				si.si5ter := omit;
+			} else {
+				si.si5ter := dec_SystemInformation(data).payload.si5ter;
+			}
+		} else if (si_type == RSL_SYSTEM_INFO_6) {
+			if (not isbound(data)) {
+				si.si6 := omit;
+			} else {
+				si.si6 := dec_SystemInformation(data).payload.si6;
+			}
+		} else {
+			handled := false;
+		}
+	}
+
+	if (not handled) {
+		setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
+	}
+}
+
+type component test_CT extends CTRL_Adapter_CT {
+	/* Array of per-BTS state */
+	var BTS_State bts[NUM_BTS];
+	/* RSL common Channel Port (for RSL_Emulation) */
+	port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
+	/* array of per-BTS RSL test ports */
+	port IPA_RSL_PT IPA_RSL[NUM_BTS];
+	port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
+	/* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
+	port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
+
+	var MGCP_Emulation_CT vc_MGCP;
+	port TELNETasp_PT BSCVTY;
+
+	/* StatsD */
+	var StatsD_Checker_CT vc_STATSD;
+
+	var RAN_Adapter g_bssap[NUM_MSC];
+	var BSSAP_LE_Adapter g_bssap_le;
+	/* for old legacy-tests only */
+	port BSSAP_CODEC_PT BSSAP;
+	port BSSAP_LE_CODEC_PT BSSAP_LE;
+
+	/* are we initialized yet */
+	var boolean g_initialized := false;
+
+	/* Osmux is enabled through VTY */
+	var boolean g_osmux_enabled := false;
+
+	/*Configure T(tias) over VTY, seconds */
+	var integer g_bsc_sccp_timer_ias :=  7 * 60;
+	/*Configure T(tiar) over VTY, seconds */
+	var integer g_bsc_sccp_timer_iar := 15 * 60;
+
+	/* global test case guard timer (actual timeout value is set in f_init()) */
+	timer T_guard := 30.0;
+
+	var CounterNameValsList g_ctr_msc;
+	var CounterNameValsList g_ctr_bsc;
+	var CounterNameValsList g_ctr_bts;
+
+	/* System Information bytes as received during RSL startup, for each RSL[idx]. */
+	var SystemInformationConfig_list g_system_information := {};
+}
+
+modulepar {
+	/* IP address at which the BSC can be reached */
+	charstring mp_bsc_ip := "127.0.0.1";
+	/* port number to which to establish the IPA OML connections */
+	integer mp_bsc_oml_port := 3002;
+	/* port number to which to establish the IPA RSL connections */
+	integer mp_bsc_rsl_port := 3003;
+	/* port number to which to establish the IPA CTRL connection */
+	integer mp_bsc_ctrl_port := 4249;
+	/* port number to which to listen for STATSD metrics */
+	integer mp_bsc_statsd_port := 8125;
+	/* IP address at which the test binds */
+	charstring mp_test_ip := "127.0.0.1";
+
+	RAN_Configurations mp_bssap_cfg := {
+		{
+			transport := BSSAP_TRANSPORT_AoIP,
+			sccp_service_type := "mtp3_itu",
+			sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
+			own_pc := 185,	/* 0.23.1 first MSC emulation */
+			own_ssn := 254,
+			peer_pc := 187, /* 0.23.3 osmo-bsc */
+			peer_ssn := 254,
+			sio := '83'O,
+			rctx := 1
+		},
+		{
+			transport := BSSAP_TRANSPORT_AoIP,
+			sccp_service_type := "mtp3_itu",
+			sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
+			own_pc := 2,	/* 0.0.2 second MSC emulation */
+			own_ssn := 254,
+			peer_pc := 187, /* 0.23.3 osmo-bsc */
+			peer_ssn := 254,
+			sio := '83'O,
+			rctx := 2
+		},
+		{
+			transport := BSSAP_TRANSPORT_AoIP,
+			sccp_service_type := "mtp3_itu",
+			sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
+			own_pc := 3,	/* 0.0.3 third MSC emulation */
+			own_ssn := 254,
+			peer_pc := 187, /* 0.23.3 osmo-bsc */
+			peer_ssn := 254,
+			sio := '83'O,
+			rctx := 3
+		}
+	};
+
+	BSSAP_LE_Configuration mp_bssap_le_cfg := {
+		sccp_service_type := "mtp3_itu",
+		sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
+		own_pc := 190,	/* 0.23.6 SMLC emulation */
+		own_ssn := 252,	/* SMLC side SSN */
+		peer_pc := 187, /* 0.23.3 osmo-bsc */
+		peer_ssn := 250, /* BSC side SSN */
+		sio := '83'O,
+		rctx := 6
+	};
+	boolean mp_enable_lcs_tests := true;
+
+	/* Whether to enable osmux tests. Can be dropped completely and enable
+	   unconditionally once new version of osmo-bsc is released (current
+	   version: 1.4.1) */
+	boolean mp_enable_osmux_test := true;
+	/* Value set in osmo-bsc.cfg "ms max power" */
+	uint8_t mp_exp_ms_power_level := 7;
+}
+
+private function f_shutdown_helper() runs on test_CT {
+	all component.stop;
+	setverdict(pass);
+	mtc.stop;
+}
+
+private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
+	var BSSAP_N_UNITDATA_ind ud_ind;
+	var boolean reset_received := false;
+	timer T := 5.0;
+	BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
+					 ts_BSSMAP_Reset(0, g_osmux_enabled)));
+	T.start;
+	alt {
+	[] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
+					       tr_BSSMAP_ResetAck(g_osmux_enabled))) {
+		log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
+		}
+	[] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
+		log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
+		BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
+			   ts_BSSMAP_ResetAck(g_osmux_enabled)));
+		reset_received := true;
+		repeat;
+		}
+	[] BSSAP.receive { repeat; }
+	[] T.timeout {
+			log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
+			/* If we received a RESET after ours was sent, it
+			   may be a race condition where the other peer beacame
+			   available after we sent it, but we are in a desired
+			   state anyway, so go forward. */
+			if (not reset_received) {
+				setverdict(fail);
+			}
+		}
+	}
+}
+
+type record IPA_Client {
+	/* IPA Emulation component reference */
+	IPA_Emulation_CT vc_IPA,
+	/* Unit-ID and other CCM parameters to use for IPA client emulation */
+	IPA_CCM_Parameters ccm_pars,
+	/* String identifier for this IPA Client */
+	charstring id,
+	/* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
+	RSL_Emulation_CT vc_RSL optional
+}
+
+/*! Start the IPA/RSL related bits for one IPA_Client.
+ *  \param clnt IPA_Client for which to establish
+ *  \param bsc_host IP address / hostname of the BSC
+ *  \param bsc_port TCP port number of the BSC
+ *  \param i number identifying this BTS
+ *  \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
+function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port, integer i,
+			 boolean handler_mode := false)
+runs on test_CT {
+	timer T := 10.0;
+
+	clnt.id := "IPA" & int2str(i) & "-RSL";
+	clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA");
+	clnt.ccm_pars := c_IPA_default_ccm_pars;
+	clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
+	clnt.ccm_pars.unit_id := int2str(1234+i) & "/0/0";
+	if (handler_mode) {
+		clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL");
+		connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[i]);
+	}
+
+	map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
+	if (handler_mode) {
+		connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
+	} else {
+		connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[i]);
+	}
+
+	clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", 10000+i, clnt.ccm_pars));
+	if (handler_mode) {
+		clnt.vc_RSL.start(RSL_Emulation.main());
+		return;
+	}
+
+	/* wait for IPA RSL link to connect and send ID ACK */
+	T.start;
+	alt {
+	[] IPA_RSL[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
+		T.stop;
+		IPA_RSL[i].send(ts_ASP_RSL_UD(ts_RSL_PAGING_LOAD_IND(23)));
+		}
+	[] IPA_RSL[i].receive(ASP_IPA_Event:?) { repeat }
+	[] IPA_RSL[i].receive { repeat }
+	[] T.timeout {
+		setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
+		mtc.stop;
+		}
+	}
+}
+
+function f_ipa_rsl_stop(inout IPA_Client clnt) runs on test_CT {
+	if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
+		return;
+	}
+	clnt.vc_IPA.stop;
+	if (isbound(clnt.vc_RSL)) {
+		clnt.vc_RSL.stop;
+	}
+}
+
+/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
+function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
+	timer T := secs_max;
+	T.start;
+	while (true) {
+		if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
+			T.stop;
+			/* the 'degraded' state exists from OML connection time, and we have to wait
+			 * until all MO's are initialized */
+			T.start(1.0);
+			T.timeout;
+			return;
+		}
+		f_sleep(0.1);
+		if (not T.running) {
+			setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
+			mtc.stop;
+		}
+	}
+}
+
+/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
+altstep as_Tguard() runs on test_CT {
+	var BSSAP_N_UNITDATA_ind ud_ind;
+	[] T_guard.timeout {
+			setverdict(fail, "Timeout of T_guard");
+			mtc.stop;
+		}
+	/* always respond with RESET ACK to RESET */
+	[] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
+		BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
+			   ts_BSSMAP_ResetAck(g_osmux_enabled)));
+		repeat;
+		}
+}
+
+altstep no_bssmap_reset() runs on test_CT {
+	[] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) {
+		setverdict(fail, "unexpected BSSMAP Reset");
+		mtc.stop;
+	}
+}
+
+function f_init_mgcp(charstring id) runs on test_CT {
+	id := id & "-MGCP";
+
+	var MGCPOps ops := {
+		create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
+		unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
+	};
+	var MGCP_conn_parameters mgcp_pars := {
+		callagent_ip := mp_bsc_ip,
+		callagent_udp_port := -1,
+		mgw_ip := mp_test_ip,
+		mgw_udp_port := 2427,
+		/* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
+		   the on  with MGCP over IPA forwarded from MSC one) */
+		multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
+	};
+
+	vc_MGCP := MGCP_Emulation_CT.create(id);
+	vc_MGCP.start(MGCP_Emulation.main(ops, mgcp_pars, id));
+}
+
+/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
+ * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
+ * OsmuxCID IE.
+ */
+private function f_vty_allow_osmux(boolean allow) runs on test_CT {
+	f_vty_enter_cfg_msc(BSCVTY, 0);
+	if (allow) {
+		f_vty_transceive(BSCVTY, "osmux on");
+	} else {
+		f_vty_transceive(BSCVTY, "osmux off");
+	}
+	f_vty_transceive(BSCVTY, "exit");
+	f_vty_transceive(BSCVTY, "exit");
+	g_osmux_enabled := allow;
+}
+
+type record of charstring Commands;
+
+private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
+{
+	f_vty_enter_cfg_cs7_inst(pt, 0);
+	for (var integer i := 0; i < sizeof(cmds); i := i+1) {
+		f_vty_transceive(pt, cmds[i]);
+	}
+	f_vty_transceive(pt, "end");
+}
+
+function f_init_vty(charstring id := "foo") runs on test_CT {
+	if (BSCVTY.checkstate("Mapped")) {
+		/* skip initialization if already executed once */
+		return;
+	}
+	map(self:BSCVTY, system:BSCVTY);
+	f_vty_set_prompts(BSCVTY);
+	f_vty_transceive(BSCVTY, "enable");
+	f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
+			  "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
+}
+
+private function f_logp(TELNETasp_PT pt, charstring log_msg)
+{
+	// log on TTCN3 log output
+	log(log_msg);
+	// log in stderr log
+	f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
+}
+
+private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
+{
+	if (rsl_idx >= lengthof(g_system_information)) {
+		g_system_information[rsl_idx] := SystemInformationConfig_omit
+	}
+	f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
+}
+
+altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
+	var ASP_RSL_Unitdata rx_rsl_ud;
+
+	/* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
+	[] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+	[] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+	[] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+	[] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+
+	/* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation  */
+	[] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+	[] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+	[] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+	[] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
+		f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
+		repeat;
+		}
+}
+
+/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
+private type record of boolean my_BooleanList;
+
+private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
+{
+	var charstring config := f_vty_transceive_ret(pt, "show running-config");
+
+	for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
+		if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
+			/* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
+			 * stepping into that config node. */
+			log("msc ", msc_nr, " is not configured, skipping");
+			continue;
+		}
+		f_vty_enter_cfg_msc(pt, msc_nr);
+		if (allow_attach_list[msc_nr]) {
+			/* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
+			f_vty_transceive(pt, "allow-attach", strict := false);
+		} else {
+			f_vty_transceive(pt, "no allow-attach", strict := false);
+		}
+		f_vty_transceive(pt, "exit");
+		f_vty_transceive(pt, "exit");
+	}
+}
+
+/* global initialization function
+ * \param nr_bts Number of BTSs we should start/bring up
+ * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
+ * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
+ */
+function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false, boolean allow_osmux := false,
+		integer nr_msc := 1, float guard_timeout := 30.0) runs on test_CT {
+	var integer bssap_idx;
+
+	if (g_initialized) {
+		return;
+	}
+	g_initialized := true;
+
+	T_guard.start(guard_timeout);
+	activate(as_Tguard());
+
+	f_init_vty("VirtMSC");
+	if (mp_enable_osmux_test) {
+		f_vty_allow_osmux(allow_osmux);
+	}
+
+	var my_BooleanList allow_attach := { false, false, false };
+	f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
+
+	for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
+		allow_attach[bssap_idx] := true;
+		/* Call a function of our 'parent component' RAN_Adapter_CT to start the
+		 * MSC-side BSSAP emulation */
+		if (handler_mode) {
+			var RanOps ranops := MSC_RanOps;
+			ranops.use_osmux := g_osmux_enabled;
+			f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
+			connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
+			f_ran_adapter_start(g_bssap[bssap_idx]);
+		} else {
+			f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
+			connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
+			f_ran_adapter_start(g_bssap[bssap_idx]);
+			f_legacy_bssap_reset();
+		}
+	}
+
+	if (mp_enable_lcs_tests) {
+		if (handler_mode) {
+			f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
+		} else {
+			f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
+			connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
+		}
+		f_bssap_le_adapter_start(g_bssap_le);
+	}
+
+	/* start the test with exactly all enabled MSCs allowed to attach */
+	f_vty_msc_allow_attach(BSCVTY, allow_attach);
+
+	f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
+
+	f_init_mgcp("VirtMSC");
+
+	for (var integer i := 0; i < nr_bts; i := i+1) {
+		f_init_bts(i, handler_mode);
+	}
+}
+
+function f_init_bts(integer bts_idx := 0, boolean handler_mode := false)
+runs on test_CT {
+	/* wait until osmo-bts-omldummy has respawned */
+	f_wait_oml(bts_idx, "degraded", 5.0);
+
+	/* start RSL connection */
+	f_ipa_rsl_start(bts[bts_idx].rsl, mp_bsc_ip, mp_bsc_rsl_port, bts_idx, handler_mode);
+	/* wait until BSC tells us "connected" */
+	f_wait_oml(bts_idx, "connected", 5.0);
+}
+
+/* expect to receive a RSL message matching a specified template on a given BTS / stream */
+function f_exp_ipa_rx(integer bts_nr, template (present) RSL_Message t_rx, float t_secs := 2.0, IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
+runs on test_CT return RSL_Message {
+	var ASP_RSL_Unitdata rx_rsl_ud;
+	timer T := t_secs;
+
+	T.start;
+	alt {
+	[] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
+		T.stop;
+		}
+	[] IPA_RSL[bts_nr].receive { repeat; }
+	[] T.timeout {
+		setverdict(fail, "Timeout expecting ", t_rx);
+		mtc.stop;
+		}
+	}
+	return rx_rsl_ud.rsl;
+}
+
+/* transmit RSL on a given BTS/stream */
+function f_ipa_tx(integer bts_nr, template (value) RSL_Message t_tx, IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
+runs on test_CT {
+	IPA_RSL[bts_nr].send(ts_ASP_RSL_UD(t_tx, sid));
+}
+
+private function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
+
+	var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+	if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
+		pars.aoip := true;
+	} else {
+		pars.aoip := false;
+	}
+	pars.exp_ms_power_level := mp_exp_ms_power_level;
+	pars.mscpool.bssap_idx := bssap_idx;
+
+	return pars;
+}
+
+type function void_fn(charstring id) runs on MSC_ConnHdlr;
+
+/* create and connect a MSC_ConnHdlr component */
+private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT {
+	connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
+	connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
+	connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
+	connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
+	if (isvalue(bts[1])) {
+		connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
+		connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
+	}
+	if (isvalue(bts[2])) {
+		connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT);
+		connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC);
+	}
+	connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
+	if (mp_enable_lcs_tests) {
+		connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
+		connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
+	}
+	connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
+	connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
+	connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
+}
+
+/* first function inside ConnHdlr component; sets g_pars + starts function */
+private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
+runs on MSC_ConnHdlr {
+	if (isvalue(pars)) {
+		g_pars := valueof(pars);
+	}
+	fn.apply(id);
+}
+
+function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
+runs on test_CT return MSC_ConnHdlr {
+	var charstring id := testcasename();
+	var MSC_ConnHdlr vc_conn;
+	var integer bssap_idx := 0;
+	if (isvalue(pars)) {
+		bssap_idx := valueof(pars).mscpool.bssap_idx;
+	}
+	vc_conn := MSC_ConnHdlr.create(id);
+	f_connect_handler(vc_conn, bssap_idx);
+	/* Emit a marker to appear in the SUT's own logging output */
+	f_logp(BSCVTY, testcasename() & "() start");
+	vc_conn.start(f_handler_init(fn, id, pars));
+	return vc_conn;
+}
+
+
+testcase TC_chan_act_to_vamos() runs on test_CT {
+	f_init_vty();
+
+	f_logp(BSCVTY, "TC_chan_act_to_vamos");
+
+	f_init(1, false);
+	f_sleep(1.0);
+
+	f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
+
+	var RSL_Message rsl;
+
+	rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+
+	var RSL_IE_Body chan_mode_ie;
+	if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, chan_mode_ie) == false) {
+		setverdict(fail, "Cannot find RSL_IE_CHAN_MODE");
+		mtc.stop;
+	}
+	if (chan_mode_ie.chan_mode.ch_rate_type != RSL_CHRT_OSMO_TCH_F_VAMOS) {
+		setverdict(fail, "expected chan_mode.ch_rate_type == RSL_CHRT_OSMO_TCH_F_VAMOS");
+		mtc.stop;
+	}
+
+	var RSL_IE_Body osmo_tsc_ie;
+	if (f_rsl_find_ie(rsl, RSL_IE_OSMO_TRAINING_SEQUENCE, osmo_tsc_ie) == false) {
+		setverdict(fail, "Cannot find RSL_IE_OSMO_TRAINING_SEQUENCE");
+		mtc.stop;
+	}
+
+	var RslChannelNr chan_nr := rsl.ies[0].body.chan_nr;
+	f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 23+10));
+
+	f_sleep(1.0);
+	f_vty_transceive(BSCVTY, "show lchan summary");
+	var charstring lchan_info := f_vty_transceive_ret(BSCVTY, "show lchan 0 0 1 0");
+	if (f_strstr(lchan_info, "State: ESTABLISHED") < 0) {
+		log("'show lchan' replied: ", lchan_info);
+		setverdict(fail, "lchan is not in state ESTABLISHED");
+		mtc.stop;
+	}
+
+	f_shutdown_helper();
+}
+
+/* generate an assignment request for either AoIP or SCCPlite */
+function f_gen_ass_req(boolean osmux_enabled := false, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
+	var PDU_BSSAP ass_cmd;
+	var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
+	if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
+		var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
+			valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
+		if (osmux_enabled) {
+			ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
+		} else {
+			ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
+		}
+	} else {
+		var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
+		ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
+	}
+	return ass_cmd;
+}
+
+/* generate an assignment complete template for either AoIP or SCCPlite */
+function f_gen_exp_compl(boolean expect_osmux := false, integer bssap_idx := 0) return template PDU_BSSAP {
+	var template PDU_BSSAP exp_compl;
+	var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
+	if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
+		if (expect_osmux) {
+			exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, osmux_cid);
+		} else {
+			exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, omit);
+		}
+	} else {
+		/* CIC is optional "*" as the MSC allocated it */
+		exp_compl := tr_BSSMAP_AssignmentComplete(*, omit);
+	}
+	return exp_compl;
+}
+
+/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
+function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
+return BSSMAP_IE_ChannelType {
+	/* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
+	var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
+	select (a_elem.codecType) {
+	case (GSM_FR) {
+		ret.channelRateAndType := ChRate_TCHF;
+		ret.speechId_DataIndicator := Spdi_TCHF_FR;
+	}
+	case (GSM_HR) {
+		ret.channelRateAndType := ChRate_TCHH;
+		ret.speechId_DataIndicator := Spdi_TCHH_HR;
+	}
+	case (GSM_EFR) {
+		ret.channelRateAndType := ChRate_TCHF;
+		ret.speechId_DataIndicator := Spdi_TCHF_EFR;
+	}
+	case (FR_AMR) {
+		ret.channelRateAndType := ChRate_TCHF;
+		ret.speechId_DataIndicator := Spdi_TCHF_AMR;
+	}
+	case (HR_AMR) {
+		ret.channelRateAndType := ChRate_TCHH;
+		ret.speechId_DataIndicator := Spdi_TCHH_AMR;
+	}
+	case else {
+		setverdict(fail, "Unsupported codec ", a_elem);
+		mtc.stop;
+	}
+	}
+	return ret;
+}
+
+
+private function f_est_lchan_and_mode_modify_to_vamos() 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);
+
+	/* puzzle together the ASSIGNMENT REQ for given codec[s] */
+	if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+		ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
+		exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
+								g_pars.ass_codec_list.codecElements[0];
+		if (isvalue(g_pars.expect_mr_s0_s7)) {
+			exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
+								g_pars.expect_mr_s0_s7;
+		}
+	}
+	ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
+				f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+	log("expecting ASS COMPL like this: ", exp_compl);
+
+	f_establish_fully(ass_cmd, exp_compl);
+
+	/* Expecting TCH/F in timeslot 1 to be active. Let's make sure. */
+	var charstring lchan_info := f_vty_transceive_ret(BSCVTY, "show lchan 0 0 1 0");
+	if (f_strstr(lchan_info, "State: ESTABLISHED") < 0) {
+		log("'show lchan' replied: ", lchan_info);
+		setverdict(fail, "lchan is not in state ESTABLISHED");
+		mtc.stop;
+	}
+
+	f_vty_transceive(BSCVTY, "vamos modify lchan 0 0 1 0 tsc 2 3");
+
+	var RSL_Message rsl_rr;
+	RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl_rr;
+
+	var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl_rr.ies[2].body.l3_info.payload);
+	log("Rx L3 from net: ", l3);
+	if (not ischosen(l3.msgs.rrm.channelModeModify)) {
+		setverdict(fail, "Expected channelModeModify message");
+		mtc.stop;
+	}
+	f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
+					 l3.msgs.rrm.channelModeModify.channelMode), rsl_rr);
+
+	var RSL_Message rsl;
+	RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl;
+
+	var RSL_IE_Body chan_mode_ie;
+	if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, chan_mode_ie) == false) {
+		setverdict(fail, "Cannot find RSL_IE_CHAN_MODE");
+		mtc.stop;
+	}
+	if (chan_mode_ie.chan_mode.ch_rate_type != RSL_CHRT_OSMO_TCH_F_VAMOS) {
+		setverdict(fail, "expected chan_mode.ch_rate_type == RSL_CHRT_OSMO_TCH_F_VAMOS");
+		mtc.stop;
+	}
+
+	var RSL_IE_Body osmo_tsc_ie;
+	if (f_rsl_find_ie(rsl, RSL_IE_OSMO_TRAINING_SEQUENCE, osmo_tsc_ie) == false) {
+		setverdict(fail, "Cannot find RSL_IE_OSMO_TRAINING_SEQUENCE");
+		mtc.stop;
+	}
+
+	RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
+	f_sleep(1.0);
+	lchan_info := f_vty_transceive_ret(BSCVTY, "show lchan 0 0 1 0");
+	if (f_strstr(lchan_info, "State: ESTABLISHED") < 0) {
+		log("'show lchan' replied: ", lchan_info);
+		setverdict(fail, "lchan is not in state ESTABLISHED");
+		mtc.stop;
+	}
+}
+
+private function f_TC_mode_modify_to_vamos(charstring id) runs on MSC_ConnHdlr {
+	f_est_lchan_and_mode_modify_to_vamos();
+}
+
+testcase TC_mode_modify_to_vamos() runs on test_CT {
+	var TestHdlrParams pars := f_gen_test_hdlr_pars();
+	var MSC_ConnHdlr vc_conn;
+
+	f_init(1, true);
+	f_sleep(1.0);
+
+	pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+	vc_conn := f_start_handler(refers(f_TC_mode_modify_to_vamos), pars);
+	vc_conn.done;
+	f_shutdown_helper();
+}
+
+private function f_est_and_reassign_to_secondary_lchan(integer reassign_to_tn := -1) runs on MSC_ConnHdlr {
+	var PDU_BSSAP ass_cmd := f_gen_ass_req();
+	var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+
+	/* puzzle together the ASSIGNMENT REQ for given codec[s] */
+	if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+		ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
+		exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
+								g_pars.ass_codec_list.codecElements[0];
+		if (isvalue(g_pars.expect_mr_s0_s7)) {
+			exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
+								g_pars.expect_mr_s0_s7;
+		}
+	}
+	ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
+				f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+	log("expecting ASS COMPL like this: ", exp_compl);
+
+	f_establish_fully(ass_cmd, exp_compl);
+
+	f_sleep(1.0);
+
+	var RslChannelNr new_chan_nr := g_chan_nr;
+	if (reassign_to_tn < 0) {
+		reassign_to_tn := g_chan_nr.tn + 1;
+	}
+	new_chan_nr.tn := reassign_to_tn;
+
+	activate(as_Media_mgw());
+
+	/* 128 is the TEI for trx 0's VAMOS shadow */
+	f_rslem_register(128, new_chan_nr, RSL_PROC);
+	log("f_rslem_register(128, new_chan_nr = ", new_chan_nr, ")");
+
+	f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0"
+			 & " reassign-to trx 0 timeslot " & int2str(new_chan_nr.tn) & " vamos-sub-slot 0 tsc 4 2");
+	/* RSL CHAN ACT is ACKed by RSL emulation */
+
+	var RSL_Message rsl;
+	var RSL_IE_Body ie;
+	var boolean b_unused;
+	interleave {
+	[] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+		var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+		log("Rx L3 from net: ", l3);
+		if (ischosen(l3.msgs.rrm.assignmentCommand)) {
+
+			var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_AssignmentComplete('00'O));
+			RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
+						 enc_PDU_ML3_MS_NW(l3_tx)));
+			
+			var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 128, new_chan_nr);
+			log("VAMOS secondary chan act was ", chan_act);
+
+		} else {
+			Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected L3 received", l3));
+		}
+		}
+	[] RSL.receive(tr_RSL_IPA_CRCX(new_chan_nr)) -> value rsl {
+		var uint7_t rtp_pt := 0;
+		if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+			rtp_pt := ie.ipa_rtp_pt;
+		}
+		RSL.send(ts_RSL_IPA_CRCX_ACK(new_chan_nr, 123,
+						oct2int(f_inet_addr("1.2.3.4")),
+						4321,
+						rtp_pt));
+		}
+	[] RSL.receive(tr_RSL_IPA_MDCX(new_chan_nr, ?)) -> value rsl{
+		/* Extract conn_id, ip, port, rtp_pt2 from request + use in response */
+		b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
+		var uint16_t conn_id := ie.ipa_conn_id;
+		/* mandatory */
+		b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
+		var HostPort peer;
+		peer.host := f_inet_ntoa(int2oct(ie.ipa_remote_ip, 4));
+		b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
+		peer.port_nr := ie.ipa_remote_port;
+		var uint7_t rtp_pt := 0;
+		/* optional */
+		if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+			rtp_pt := ie.ipa_rtp_pt;
+		}
+		RSL.send(ts_RSL_IPA_MDCX_ACK(new_chan_nr, conn_id,
+						oct2int(f_inet_addr(peer.host)),
+						peer.port_nr,
+						rtp_pt));
+		}
+	[] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
+	[] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+		/*
+		RSL.send(ts_ASP_RSL_UD(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr),
+				       IPAC_PROTO_RSL_TRX0));
+		*/
+		}
+	/* (There must be no RSL_MT_REL_REQ on the old lchan.) */
+	}
+
+	f_sleep(1.0);
+	f_vty_transceive(BSCVTY, "show lchan summary");
+	f_sleep(5.0);
+}
+
+private function f_TC_assign_to_secondary_lchan(charstring id) runs on MSC_ConnHdlr {
+	f_est_and_reassign_to_secondary_lchan();
+}
+
+testcase TC_assign_to_secondary_lchan() runs on test_CT {
+	var TestHdlrParams pars := f_gen_test_hdlr_pars();
+	var MSC_ConnHdlr vc_conn;
+
+	f_init(1, true);
+	f_sleep(1.0);
+
+	pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+	vc_conn := f_start_handler(refers(f_TC_assign_to_secondary_lchan), pars);
+	vc_conn.done;
+	f_shutdown_helper();
+}
+
+private function f_TC_vamos_multiplex_tch_f_tch_f1(charstring id) runs on MSC_ConnHdlr {
+	f_est_lchan_and_mode_modify_to_vamos();
+	f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
+}
+
+private function f_TC_vamos_multiplex_tch_f_tch_f2(charstring id) runs on MSC_ConnHdlr {
+	f_est_and_reassign_to_secondary_lchan(1);
+}
+
+testcase TC_vamos_multiplex_tch_f_tch_f() runs on test_CT {
+	var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+	var MSC_ConnHdlr vc_conn1;
+
+	var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+	var MSC_ConnHdlr vc_conn2;
+	pars2.imsi := '001014234234234'H;
+	pars2.media_nr := 2;
+
+	f_init(1, true);
+	f_sleep(1.0);
+
+	pars1.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+	pars2.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+	vc_conn1 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f1), pars1);
+	vc_conn1.done;
+
+	vc_conn2 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f2), pars2);
+	vc_conn2.done;
+	f_shutdown_helper();
+}
+
+control {
+	execute( TC_mode_modify_to_vamos() );
+	execute( TC_chan_act_to_vamos() );
+	execute( TC_assign_to_secondary_lchan() );
+	execute( TC_vamos_multiplex_tch_f_tch_f() );
+}
+
+}

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/24411
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I2c504099163a30ea102cbd26d3615ca2e5ce1e64
Gerrit-Change-Number: 24411
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210525/8a3f456d/attachment.htm>


More information about the gerrit-log mailing list