Change in osmo-ttcn3-hacks[master]: msc: overhaul voice call testing

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
Sun Nov 3 23:18:12 UTC 2019


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


Change subject: msc: overhaul voice call testing
......................................................................

msc: overhaul voice call testing

* Semantic:

We don't really know which side the MSC first creates a CRCX for. Instead of
assuming that the RAN side is always CRCX'd first, simply handle a "first" and
a "second" CRCX, not making any assumptions which is for which side.
Notably, there still are quite a few places assuming which CRCX corresponds to
the RAN/CN side, but the changes are sufficient to still pass the tests when
osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for
example because it doesn't matter that the wrong port number is returned during
a subsequent MDCX... Cleaning up the rest is still todo for later.

Remove code dup from call establishing code, particularly for MGCP.

Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of
the call establishing tests handle upcoming changes in osmo-msc's order of
messages, without re-implementing the changes for each test individually.

The X-Osmux parameter was so far expected to appear in the first CRCX received,
assuming that this first CRCX is for the RAN.  Instead, detect whether X-Osmux
is contained in a CRCX, and reply with an Osmux CID if so, regardless of it
being the first or second CRCX.  Count the number of X-Osmux parameters
received in CRCX messages, and compare after call setup to verify X-Osmux
presence.

Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that
worked with the older code dup will break by this patch. This is fixed by a
subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec.

* Details, per patch chunk:

Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a
wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX
first, the RAN port number can be one or the other).

Split f_mgcp_find_param_entry() out of f_mgcp_find_param() to be able to act on
an MgcpParameterList without an enclosing MgcpMessage.

In CallParameters, move MGCP handling instructions into a separate record
"CrcxResponse", and have two of them for handling the first and the second
CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}.

In CallParameters, add some flags for early-exiting call establishment with a
particular desired behavior, for specialized tests.

In CallParameters, use common default values and don't repeat them in each and
every call establishing test.

Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish()
are invoked.

Remove CRCX comments implying RAN or CN side, instead just talk of the "first"
and the "second" CRCX.

Implement one common f_handle_crcx() function, which is used by
f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and
implicitly uses the first/second CRCX handling.

For Assigment, use a wildcard RTP port so that we don't have to assume which
CRCX was for the RAN side.

In f_mo_call_establish(), insert special case conditions to make it enact
errors at specific times, for individual tests. That saves re-implementing the
entire call establishment (code dup).

For error cases, add expectation of a CC Release message in the call
establishment. This should not apply for normal successful operation, but
because interleave does not support conditionals, add flags
got_mncc_setup_compl_ind and got_cc_connect to break the interleave when
establishing is complete, so that the CC Release is skipped.
A CC Release always breaks the interleave, at whatever time it arrives.

Tests adopting f_{mo,mt}_call instead of code dup:
  f_tc_mo_setup_and_nothing()
  f_tc_mo_crcx_ran_timeout()
  f_tc_mo_crcx_ran_reject()
  f_tc_mo_release_timeout()
  f_tc_mo_cc_bssmap_clear()

Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
---
M library/BSSMAP_Templates.ttcn
M library/MGCP_Templates.ttcn
M msc/BSC_ConnectionHandler.ttcn
M msc/MSC_Tests.ttcn
4 files changed, 294 insertions(+), 345 deletions(-)



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

diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn
index 41755db..b40ec61 100644
--- a/library/BSSMAP_Templates.ttcn
+++ b/library/BSSMAP_Templates.ttcn
@@ -407,15 +407,15 @@
 	return cic;
 }
 
-template (value) BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA(BSSMAP_FIELD_IPAddress addr,
-									    uint16_t udp_port,
+template BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA(BSSMAP_FIELD_IPAddress addr,
+									    template uint16_t udp_port,
 									    integer len) := {
 	elementIdentifier := '7C'O,
 	lengthIndicator := len, /* overwritten */
 	ipAddress := addr,
 	uDPPortValue := udp_port
 }
-template (value) BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA4(OCT4 ip, uint16_t pt) :=
+template BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA4(OCT4 ip, template uint16_t pt) :=
 							ts_BSSMAP_IE_AoIP_TLA({ipv4:=ip}, pt, 6);
 template (value) BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA6(OCT16 ip, uint16_t pt) :=
 							ts_BSSMAP_IE_AoIP_TLA({ipv6:=ip}, pt, 18);
diff --git a/library/MGCP_Templates.ttcn b/library/MGCP_Templates.ttcn
index dae379e..e03fd8e 100644
--- a/library/MGCP_Templates.ttcn
+++ b/library/MGCP_Templates.ttcn
@@ -453,6 +453,17 @@
 		sdp := *
 	}
 
+	function f_mgcp_find_param_entry(MgcpParameterList pars, MgcpInfoCode code, out charstring ret)
+	return boolean {
+		for (var integer i := 0; i < sizeof(pars); i := i+1) {
+			if (pars[i].code == code) {
+				ret := pars[i].val;
+				return true;
+			}
+		}
+		return false;
+	}
+
 	function f_mgcp_find_param(MgcpMessage msg, MgcpInfoCode code, out charstring ret)
 	return boolean {
 		var MgcpParameterList pars;
@@ -461,13 +472,7 @@
 		} else {
 			pars := msg.response.params;
 		}
-		for (var integer i := 0; i < sizeof(pars); i := i+1) {
-			if (pars[i].code == code) {
-				ret := pars[i].val;
-				return true;
-			}
-		}
-		return false;
+		return f_mgcp_find_param_entry(pars, code, ret);
 	}
 
 	/* template to determine if a MGCP endpoint is a wildcard endpoint */
diff --git a/msc/BSC_ConnectionHandler.ttcn b/msc/BSC_ConnectionHandler.ttcn
index 7a94d85..23697da 100644
--- a/msc/BSC_ConnectionHandler.ttcn
+++ b/msc/BSC_ConnectionHandler.ttcn
@@ -676,6 +676,13 @@
 	/* re-configure MSC behaviour via VTY */
 }
 
+type record CrcxResponse {
+	integer resp,	/* 1 = reply with OK, 0 = do not reply, -1 = reply with error */
+	HostName mgw_rtp_ip,
+	PortNumber mgw_rtp_port,
+	MgcpConnectionId mgcp_connection_id	/* MGCP Connection ID BSS Side */
+}
+
 /* parameters related to a (MO?) voice call */
 type record CallParameters {
 	/* CC related parameters */
@@ -695,24 +702,24 @@
 	PortNumber bss_rtp_port optional,		/* BSS Side RTP Port */
 	HostName mss_rtp_ip optional,			/* MSS Side RTP IP */
 	PortNumber mss_rtp_port optional,		/* MSS Side RTP Port */
-	HostName mgw_rtp_ip_bss,			/* BSS-facing MGW RTP IP */
-	PortNumber mgw_rtp_port_bss,			/* BSS-facing MGW RTP Port */
-	HostName mgw_rtp_ip_mss,			/* MSS-facing MGW RTP IP */
-	PortNumber mgw_rtp_port_mss,			/* MSS-facing MGW RTP Port */
+	integer got_crcx_count,
+	CrcxResponse mgw_conn_1,
+	CrcxResponse mgw_conn_2,
 	uint7_t rtp_payload_type,			/* dynamic RTP payload type */
 	charstring rtp_sdp_format,			/* AMR/8000 or the like */
 	boolean mgw_drop_dlcx optional,			/* Provoke errors by not responding to DLCX
 							   (f_mt_call and f_mt_call) */
+	boolean stop_after_cc_setup,			/* Special case: stop call establish after CC Setup */
+	boolean ran_clear_when_alerting,		/* Special case: send Clear upon CC Alerting */
 
 	MgcpCallId mgcp_call_id optional,		/* MGCP Call ID; CallAgent allocated */
 	MgcpEndpoint mgcp_ep optional			/* MGCP Endpoint, CallAgent or MGW allocated */,
-	MgcpConnectionId mgcp_connection_id_bss,	/* MGCP Connection ID BSS Side */
-	MgcpConnectionId mgcp_connection_id_mss,	/* MGCP Connection ID MSS Side */
 
-	boolean use_osmux				/* MSC is expected to use Osmux for this call */
+	boolean use_osmux,				/* MSC is expected to use Osmux for this call */
+	integer got_osmux
 }
 
-template (value) CallParameters t_CallParams(hexstring called, integer tid) := {
+template (value) CallParameters t_CallParams(hexstring called := '12345'H, integer tid := 0) := {
 	called_party := called,
 	transaction_id := tid,
 	mo_call := false,
@@ -724,32 +731,43 @@
 	bss_rtp_port := 9000,
 	mss_rtp_ip := omit,
 	mss_rtp_port := omit,
-	mgw_rtp_ip_bss := "1.1.1.1",
-	mgw_rtp_port_bss := 10000,
-	mgw_rtp_ip_mss := "1.1.1.1",
-	mgw_rtp_port_mss := 11000,
+	got_crcx_count := 0,
+	mgw_conn_1 := {
+		resp := 1,
+		mgw_rtp_ip := "1.1.1.1",
+		mgw_rtp_port := 10000,
+		mgcp_connection_id := '11111'H
+	},
+	mgw_conn_2 := {
+		resp := 1,
+		mgw_rtp_ip := "1.1.1.1",
+		mgw_rtp_port := 11000,
+		mgcp_connection_id := '22222'H
+	},
 	rtp_payload_type := 98,
 	rtp_sdp_format := "AMR/8000",
 	mgw_drop_dlcx := false,
+	stop_after_cc_setup := false,
+	ran_clear_when_alerting := false,
 	mgcp_call_id := omit,
-	mgcp_ep := omit,
-	mgcp_connection_id_bss := '0'H,//
-	mgcp_connection_id_mss := '0'H,//
-	use_osmux := false
+	mgcp_ep := "rtpbridge/1 at mgw",
+	use_osmux := false,
+	got_osmux := 0
 };
 
 /* Allocate a call reference and send SETUP via MNCC to MSC */
 function f_mt_call_initate(inout CallParameters cpars)
 runs on BSC_ConnHdlr {
+	cpars.mo_call := false;
 	cpars.mncc_callref := f_rnd_int(2147483648);
 	MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
 					hex2str(cpars.called_party), hex2str(g_pars.imsi)));
 }
 
 private template (value) SDP_Message ts_SDP_CRCX_CN(CallParameters cpars) :=
-	ts_SDP(cpars.mgw_rtp_ip_mss, cpars.mgw_rtp_ip_mss,
+	ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
 		hex2str(cpars.mgcp_call_id), "42",
-		cpars.mgw_rtp_port_mss,
+		cpars.mgw_conn_2.mgw_rtp_port,
 		{ int2str(cpars.rtp_payload_type) },
 		{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
 		  cpars.rtp_sdp_format)),
@@ -770,6 +788,8 @@
 
 	log("f_mt_call_complete 1");
 
+	cpars.got_osmux := 0;
+
 	/* MS <- MSC: Expect CC SETUP */
 	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
 
@@ -783,53 +803,26 @@
 	/* Ask MSC via MNCC to create the RTP socket on the MSC/MGW side */
 	MNCC.send(ts_MNCC_RTP_CREATE(cpars.mncc_callref));
 
-	/* First MGCP CRCX (for BSS/RAN side) */
+	/* First MGCP CRCX */
 	MGCP.receive(tr_CRCX) -> value mgcp_cmd {
 		log("f_mt_call_complete 3");
-		cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
-
-		/* When the endpoint contains a wildcard we keep the endpoint
-		 * identifier we have set up in cpars. Otherwise we use the
-		 * endpoint name that the call agent has supplied */
-		if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
-			cpars.mgcp_ep := mgcp_cmd.line.ep;
+		if (not f_handle_crcx(cpars, mgcp_cmd)) {
+			return;
 		}
-
-		var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_bss, cpars.mgw_rtp_ip_bss,
-							hex2str(cpars.mgcp_call_id), "42",
-							cpars.mgw_rtp_port_bss,
-							{ int2str(cpars.rtp_payload_type) },
-							{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
-										cpars.rtp_sdp_format)),
-							  valueof(ts_SDP_ptime(20)) }));
-
-		if (cpars.use_osmux) {
-			osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
-			if (osmux_cid != -1) { /* we expect MSC to use wildcard here */
-				setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
-				mtc.stop;
-			}
-			osmux_cid := 0;
-			mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_bss, osmux_cid, sdp);
-		} else {
-			mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_bss, sdp);
-		}
-
-		f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(cpars.mgcp_ep));
-		MGCP.send(mgcp_resp);
 		}
 
 
 	if (g_pars.ran_is_geran) {
-		var BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
-			valueof(ts_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.mgw_rtp_ip_bss),cpars.mgw_rtp_port_bss));
+		var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
+			ts_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.mgw_conn_1.mgw_rtp_ip), ?);
 
 		interleave {
 		/* Second MGCP CRCX (this time for MSS/CN side) */
 		[] MGCP.receive(tr_CRCX(cpars.mgcp_ep)) -> value mgcp_cmd {
 			log("f_mt_call_complete 4");
-			var SDP_Message sdp := valueof(ts_SDP_CRCX_CN(cpars));
-			MGCP.send(ts_CRCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp));
+			if (not f_handle_crcx(cpars, mgcp_cmd)) {
+				break;
+			}
 			}
 
 		/* MSC acknowledges the MNCC_CREATE to the MNCC handler */
@@ -839,7 +832,7 @@
 
 		/* expect the MSC to trigger a BSSMAP ASSIGNMENT */
 		[] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, tla_ass)) -> value bssap {
-			var BSSMAP_IE_AoIP_TransportLayerAddress tla;
+			var template BSSMAP_IE_AoIP_TransportLayerAddress tla;
 			var BSSMAP_IE_SpeechCodec codec;
 			var BSSMAP_IE_Osmo_OsmuxCID osmuxCID;
 			log("f_mt_call_complete 6");
@@ -853,8 +846,8 @@
 					mtc.stop;
 				}
 				osmuxCID := valueof(ts_OsmuxCID(0));
-				if (cpars.use_osmux and not match(bssap.pdu.bssmap.assignmentRequest.osmuxCID, osmuxCID)) {
-					setverdict(fail, "MSC sent AssignReq without expected OsmuxCID IE");
+				if (not match(bssap.pdu.bssmap.assignmentRequest.osmuxCID, osmuxCID)) {
+					setverdict(fail, "MSC sent AssignReq without expected OsmuxCID IE. Expected ", osmuxCID, " Got ", bssap.pdu.bssmap.assignmentRequest.osmuxCID);
 					mtc.stop;
 				}
 				bssap := valueof(ts_BSSMAP_AssignmentComplete(omit, tla, codec, osmuxCID));
@@ -877,9 +870,9 @@
 		/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
 		[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
 			log("f_mt_call_complete 8");
-			var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_mss, cpars.mgw_rtp_ip_mss,
+			var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
 								hex2str(cpars.mgcp_call_id), "42",
-								cpars.mgw_rtp_port_mss,
+								cpars.mgw_conn_2.mgw_rtp_port,
 								{ int2str(cpars.rtp_payload_type) },
 								{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
 											cpars.rtp_sdp_format)),
@@ -890,9 +883,9 @@
 					setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != 0");
 					mtc.stop;
 				}
-				mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_bss, osmux_cid, sdp);
+				mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
 			} else {
-				mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp);
+				mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp);
 			}
 			MGCP.send(mgcp_resp);
 			}
@@ -900,25 +893,25 @@
 		/* MDCX setting up the CN side remote RTP address received from MNCC CONNECT */
 		[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
 			log("f_mt_call_complete 9");
-			var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_mss, cpars.mgw_rtp_ip_mss,
+			var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
 								hex2str(cpars.mgcp_call_id), "42",
-								cpars.mgw_rtp_port_mss,
+								cpars.mgw_conn_2.mgw_rtp_port,
 								{ int2str(cpars.rtp_payload_type) },
 								{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
 											cpars.rtp_sdp_format)),
 								  valueof(ts_SDP_ptime(20)) }));
-			MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp));
+			MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp));
 			}
 
 		}
 	} else {
-		var template TransportLayerAddress rab_tla := ? /* FIXME: encode the mgw_rtp_ip_bss/mgw_rtp_port_bss */
+		var template TransportLayerAddress rab_tla := ? /* FIXME: encode the mgw_rtp_ip/mgw_rtp_port */
 		var template RAB_SetupOrModifyList rab_sml := tr_RAB_SML(rab_id := ?, tla := rab_tla, binding_id := ?);
 
 		interleave {
 		[] MGCP.receive(tr_CRCX(cpars.mgcp_ep)) -> value mgcp_cmd {
 			var SDP_Message sdp := valueof(ts_SDP_CRCX_CN(cpars));
-			MGCP.send(ts_CRCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp));
+			MGCP.send(ts_CRCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp));
 			/* MSC acknowledges the MNCC_CREATE to the MNCC handler */
 			MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref));
 			}
@@ -930,6 +923,13 @@
 		}
 	}
 
+	if (cpars.use_osmux == (cpars.got_osmux != 0)) {
+		log("Osmux ok: use_osmux = ", cpars.use_osmux, " got_osmux = ", cpars.got_osmux);
+	} else {
+		setverdict(fail, "Osmux failure: use_osmux = ", cpars.use_osmux, " got_osmux = ", cpars.got_osmux);
+		mtc.stop;
+	}
+
 	log("f_mt_call_complete DONE");
 }
 
@@ -958,6 +958,139 @@
 	setverdict(pass);
 }
 
+/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
+ * Return true when an OK reply was sent, false otherwise.
+ * Count occurence of Osmux, include Osmux parameters in the reply if necessary. */
+function f_handle_crcx(inout CallParameters cpars, MgcpCommand mgcp_cmd)
+runs on BSC_ConnHdlr
+return boolean {
+	var CrcxResponse conn := cpars.mgw_conn_1;
+	if (cpars.got_crcx_count > 0) {
+		conn := cpars.mgw_conn_2;
+	}
+	cpars.got_crcx_count := cpars.got_crcx_count + 1;
+
+	var MgcpMessage mgcp_msg := {
+		command := mgcp_cmd
+	}
+	var template MgcpResponse mgcp_resp;
+	var MgcpOsmuxCID osmux_cid;
+	var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
+	if (ispresent(cpars.mgcp_call_id)) {
+		if (cpars.mgcp_call_id != call_id) {
+			setverdict(fail, "CRCX contained unexpected call id. Expected:", cpars.mgcp_call_id, " got:", call_id);
+			mtc.stop;
+		}
+	} else {
+		cpars.mgcp_call_id := call_id;
+	}
+
+	/* When the endpoint contains a wildcard we keep the endpoint
+	 * identifier we have set up in cpars. Otherwise we use the
+	 * endpoint name that the call agent has supplied */
+	if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
+		cpars.mgcp_ep := mgcp_cmd.line.ep;
+	}
+
+	if (conn.resp == -1) {
+		/* Reply with error */
+		var MgcpResponse mgcp_rsp := {
+			line := {
+				code := "542",
+				trans_id := mgcp_cmd.line.trans_id,
+				string := "FORCED_FAIL"
+			},
+			sdp := omit
+
+		}
+		var MgcpParameter mgcp_rsp_param := {
+			code := "Z",
+			val := cpars.mgcp_ep
+		};
+		mgcp_rsp.params[0] := mgcp_rsp_param;
+		MGCP.send(mgcp_rsp);
+		return false;
+	}
+
+	if (conn.resp == 0) {
+		/* Do not reply at all */
+		return false;
+	}
+
+	if (conn.resp != 1) {
+		setverdict(fail, "Unexpected value for cpars.mgw_conn_*.resp, expect -1, 0 or 1");
+		mtc.stop;
+	}
+
+	var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
+						hex2str(cpars.mgcp_call_id), "42",
+						conn.mgw_rtp_port,
+						{ int2str(cpars.rtp_payload_type) },
+						{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
+									cpars.rtp_sdp_format)),
+						  valueof(ts_SDP_ptime(20)) }));
+
+	if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
+		if (not cpars.use_osmux) {
+			setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
+			mtc.stop;
+		}
+		cpars.got_osmux := cpars.got_osmux + 1;
+		/* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
+		osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
+		log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
+		if (osmux_cid != -1) {
+			setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
+			mtc.stop;
+		}
+
+		osmux_cid := 0;
+		mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
+	} else {
+		mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
+	}
+
+	f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(cpars.mgcp_ep));
+	MGCP.send(mgcp_resp);
+	return true;
+}
+
+
+altstep as_optional_mgcp_crcx(CallParameters cpars) runs on BSC_ConnHdlr {
+	var MgcpCommand mgcp_cmd;
+	[] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
+		log("as_optional_mgcp_crcx: rx CRCX");
+		f_handle_crcx(cpars, mgcp_cmd);
+
+		/* Without this 'repeat', the as_optional_mgcp_crcx() exits currently waiting interleaves as soon as an
+		 * CRCX is handled. */
+		repeat;
+		}
+}
+
+private altstep as_optional_mgcp_mdcx(HostName mgw_rtp_ip, PortNumber mgw_rtp_port) runs on BSC_ConnHdlr {
+	var MgcpCommand mgcp_cmd;
+	[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
+		log("as_optional_mgcp_mdcx: rx MDCX");
+		log(mgcp_cmd);
+		var charstring conn_id;
+		var charstring rtp_payload_type;
+		f_mgcp_find_param_entry(mgcp_cmd.params, "I", conn_id);
+		rtp_payload_type := mgcp_cmd.sdp.media_list[0].media_field.fmts[0];
+
+		var SDP_Message sdp := valueof(ts_SDP(mgw_rtp_ip, mgw_rtp_ip,
+							mgcp_cmd.sdp.origin.session_id, "42",
+							mgw_rtp_port,
+							{ rtp_payload_type },
+							{ valueof(ts_SDP_ptime(20)) }));
+		MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, str2hex(conn_id), sdp));
+
+		/* Without this 'repeat', currently active other interleave and alt series exit as soon as an MDCX is
+		 * handled. */
+		repeat;
+	}
+}
+
 function f_mo_call_establish(inout CallParameters cpars)
 runs on BSC_ConnHdlr {
 
@@ -968,6 +1101,8 @@
 	var PDU_BSSAP bssap;
 	var MgcpOsmuxCID osmux_cid;
 
+	cpars.mo_call := true;
+
 	if (cpars.emergency) {
 		f_establish_fully(EST_TYPE_EMERG_CALL);
 	} else {
@@ -984,8 +1119,14 @@
 		BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
 	}
 
-	var BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
-		valueof(ts_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.mgw_rtp_ip_bss),cpars.mgw_rtp_port_bss));
+	if (cpars.stop_after_cc_setup) {
+		return;
+	}
+
+	var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
+		ts_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.mgw_conn_1.mgw_rtp_ip), ?);
+
+	var default mdcx := activate(as_optional_mgcp_mdcx(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_port));
 
 	interleave {
 	[] MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc {
@@ -994,43 +1135,20 @@
 		MNCC.send(ts_MNCC_RTP_CREATE(cpars.mncc_callref));
 		}
 
-	/* First MGCP CRCX (for BSS/RAN side) */
+	/* First MGCP CRCX */
 	[] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
 		log("f_mo_call_establish 2: rx 1st CRCX");
-		cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
-
-		/* When the endpoint contains a wildcard we keep the endpoint
-		 * identifier we have set up in cpars. Otherwise we use the
-		 * endpoint name that the call agent has supplied */
-		if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
-			cpars.mgcp_ep := mgcp_cmd.line.ep;
+		if (not f_handle_crcx(cpars, mgcp_cmd)) {
+			break;
+		}
 		}
 
-		if (cpars.use_osmux) {
-			osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
+	/* Second MGCP CRCX */
+	[] MGCP.receive(tr_CRCX(cpars.mgcp_ep)) -> value mgcp_cmd {
+		log("f_mo_call_establish 6: rx 2nd CRCX");
+		if (not f_handle_crcx(cpars, mgcp_cmd)) {
+			break;
 		}
-
-		var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_bss, cpars.mgw_rtp_ip_bss,
-							hex2str(cpars.mgcp_call_id), "42",
-							cpars.mgw_rtp_port_bss,
-							{ int2str(cpars.rtp_payload_type) },
-							{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
-										cpars.rtp_sdp_format)),
-							  valueof(ts_SDP_ptime(20)) }));
-
-		if (cpars.use_osmux) {
-			osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
-			if (osmux_cid != -1) { /* we expect MSC to use wildcard here */
-				setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
-				mtc.stop;
-			}
-			osmux_cid := 0;
-			mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_bss, osmux_cid, sdp);
-		} else {
-			mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_bss, sdp);
-		}
-		f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(cpars.mgcp_ep));
-		MGCP.send(mgcp_resp);
 		}
 
 	[] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref)) {
@@ -1050,7 +1168,7 @@
 		var BSSMAP_IE_SpeechCodec codec;
 		var BSSMAP_IE_Osmo_OsmuxCID osmuxCID;
 
-		if (tla_ass != bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer) {
+		if (not match(bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer, tla_ass)) {
 			log("Expected:", tla_ass);
 			log("Got:", bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer);
 			setverdict(fail, "MSC sent Assignment Request with unexpected AoIP Transport Layer IE");
@@ -1084,9 +1202,9 @@
 	/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
 	[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
 		log("f_mo_call_establish 5: rx MDCX for the RAN side");
-		var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_mss, cpars.mgw_rtp_ip_mss,
+		var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
 							hex2str(cpars.mgcp_call_id), "42",
-							cpars.mgw_rtp_port_mss,
+							cpars.mgw_conn_2.mgw_rtp_port,
 							{ int2str(cpars.rtp_payload_type) },
 							{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
 										cpars.rtp_sdp_format)),
@@ -1098,22 +1216,25 @@
 				setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != 0");
 				mtc.stop;
 			}
-			mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_bss, osmux_cid, sdp);
+			mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
 		} else {
-			mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp);
+			mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp);
 		}
 		MGCP.send(mgcp_resp);
 		}
 
-	/* Second MGCP CRCX (this time for MSS/CN side) */
-	[] MGCP.receive(tr_CRCX(cpars.mgcp_ep)) -> value mgcp_cmd {
-		log("f_mo_call_establish 6: rx 2nd CRCX, for CN side");
-		var SDP_Message sdp := valueof(ts_SDP_CRCX_CN(cpars));
-		MGCP.send(ts_CRCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp));
-		}
-
 	[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id))) {
 		log("f_mo_call_establish 7: rx CC Alerting");
+
+		if (cpars.ran_clear_when_alerting) {
+			if (g_pars.ran_is_geran) {
+				BSSAP.send(ts_BSSMAP_ClearRequest(0));
+			} else {
+				BSSAP.send(ts_RANAP_IuReleaseRequest(ts_RanapCause_om_intervention));
+			}
+			break;
+		}
+
 		cpars.mncc_callref := mncc.u.signal.callref;
 		/* Call Proceeding */
 		MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
@@ -1127,33 +1248,32 @@
 		log("f_mo_call_establish 8: rx MNCC SETUP COMPLETE ind");
 		}
 
-	/* second MDCX setting up the CN side remote RTP address and codec received from MNCC RTP CONNECT */
-	[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
-		log("f_mo_call_establish 9: rx MDCX for CN side");
-		var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_mss, cpars.mgw_rtp_ip_mss,
-							hex2str(cpars.mgcp_call_id), "42",
-							cpars.mgw_rtp_port_mss,
-							{ int2str(cpars.rtp_payload_type) },
-							{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
-										cpars.rtp_sdp_format)),
-							  valueof(ts_SDP_ptime(20)) }));
-		MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp));
-		}
-
 	[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CONNECT(cpars.transaction_id))) {
 		log("f_mo_call_establish 10: rx CC CONNECT");
 		BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CONNECT_ACK(cpars.transaction_id)));
 		}
+
+	[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
+		log("f_mo_call_establish 11: rx CC RELEASE");
+		f_expect_clear();
+		break;
+		}
+	}
+
+	f_sleep(0.5);
+	deactivate(mdcx);
+
+	if (cpars.use_osmux == (cpars.got_osmux != 0)) {
+		log("Osmux ok: use_osmux = ", cpars.use_osmux, " got_osmux = ", cpars.got_osmux);
+	} else {
+		setverdict(fail, "Osmux failure: use_osmux = ", cpars.use_osmux, " got_osmux = ", cpars.got_osmux);
+		mtc.stop;
 	}
 
 	log("f_mo_call_establish DONE");
 	setverdict(pass);
 }
 
-private altstep as_optional_mgcp_mdcx() runs on BSC_ConnHdlr {
-	[] MGCP.receive(tr_MDCX) {};
-}
-
 function f_call_hangup(inout CallParameters cpars, boolean release_by_ms, boolean is_csfb := false)
 runs on BSC_ConnHdlr {
 
@@ -1194,7 +1314,7 @@
 
 	respond_to_dlcx := not (isbound(cpars.mgw_drop_dlcx) and valueof(cpars.mgw_drop_dlcx));
 
-	var default mdcx := activate(as_optional_mgcp_mdcx());
+	var default mdcx := activate(as_optional_mgcp_mdcx(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_port));
 
 	/* clearing of radio channel */
 	interleave {
diff --git a/msc/MSC_Tests.ttcn b/msc/MSC_Tests.ttcn
index c290d7c..b4db43d 100644
--- a/msc/MSC_Tests.ttcn
+++ b/msc/MSC_Tests.ttcn
@@ -608,12 +608,7 @@
 
 friend function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
-	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '22222'H;
-	cpars.mgcp_connection_id_mss := '33333'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-
+	var CallParameters cpars := valueof(t_CallParams);
 	f_perform_lu();
 	f_mo_call(cpars);
 }
@@ -939,7 +934,6 @@
 private function f_emerg_call(MobileIdentityLV mi) runs on BSC_ConnHdlr {
 	var CallParameters cpars := valueof(t_CallParams('112'H, 0));
 	cpars.emergency := true;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
 
 	f_mo_call(cpars);
 }
@@ -1213,14 +1207,14 @@
 	f_init_handler(pars, 190.0);
 
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
+	cpars.mgw_conn_2.resp := 0;
+	cpars.stop_after_cc_setup := true;
+
+	f_vty_config(MSCVTY, "msc", "mncc guard-timeout 20");
 
 	f_perform_lu();
 
-	f_establish_fully();
-	f_create_mncc_expect(hex2str(cpars.called_party));
-	f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
-
-	BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
+	f_mo_call_establish(cpars);
 
 	var default ccrel := activate(as_optional_cc_rel(cpars));
 
@@ -1247,28 +1241,15 @@
 	var MgcpCommand mgcp_cmd;
 
 	f_perform_lu();
+	/* Do not respond to the second CRCX */
+	cpars.mgw_conn_2.resp := 0;
+	f_mo_call_establish(cpars);
 
-	f_establish_fully();
-	f_create_mncc_expect(hex2str(cpars.called_party));
-	f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+	var default ccrel := activate(as_optional_cc_rel(cpars));
 
-	BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
-	MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
-	cpars.mncc_callref := mncc.u.signal.callref;
-	MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
+	f_expect_clear(60.0);
 
-	MGCP.receive(tr_CRCX) -> value mgcp_cmd;
-	cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
-	cpars.mgcp_ep := mgcp_cmd.line.ep;
-	/* never respond to this */
-
-	/* When the connection with the MGW fails, the MSC will first request
-	 * a release via call control. We will answer this request normally. */
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
-	BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
-
-	f_expect_clear(30.0);
+	deactivate(ccrel);
 }
 testcase TC_mo_crcx_ran_timeout() runs on MTC_CT {
 	var BSC_ConnHdlr vc_conn;
@@ -1282,75 +1263,18 @@
 /* Test MO Call with reject to RAN-side CRCX */
 friend function f_tc_mo_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
+
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	var MNCC_PDU mncc;
-	var MgcpCommand mgcp_cmd;
+
+	/* Respond with error for the first CRCX */
+	cpars.mgw_conn_1.resp := -1;
 
 	f_perform_lu();
+	f_mo_call_establish(cpars);
 
-	f_establish_fully();
-	f_create_mncc_expect(hex2str(cpars.called_party));
-	f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
-
-	BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
-	MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
-	cpars.mncc_callref := mncc.u.signal.callref;
-	MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
-
-	MGCP.receive(tr_CRCX) -> value mgcp_cmd;
-
-	/* Detect if the received CRCX is a wildcarded CRCX request. If yes,
-	 * set an endpoint name that fits the pattern. If not, just use the
-	 * endpoint name from the request */
-	if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
-		cpars.mgcp_ep := "rtpbridge/1 at mgw";
-	} else {
-		cpars.mgcp_ep := mgcp_cmd.line.ep;
-	}
-
-	cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
-
-	/* Respond to CRCX with error */
-	var MgcpResponse mgcp_rsp := {
-		line := {
-			code := "542",
-			trans_id := mgcp_cmd.line.trans_id,
-			string := "FORCED_FAIL"
-		},
-		sdp := omit
-	}
-	var MgcpParameter mgcp_rsp_param := {
-		code := "Z",
-		val := cpars.mgcp_ep
-	};
-	mgcp_rsp.params[0] := mgcp_rsp_param;
-	MGCP.send(mgcp_rsp);
-
-	timer T := 30.0;
-	T.start;
-	alt {
-	[] T.timeout {
-		setverdict(fail, "Timeout waiting for channel release");
-		mtc.stop;
-		}
-	[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
-		BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
-		repeat;
-		}
-	[] MNCC.receive { repeat; }
-	[] GSUP.receive { repeat; }
-	/* Note: As we did not respond properly to the CRCX from the MSC we
-	 * expect the MSC to omit any further MGCP operation (At least in the
-	 * the current implementation, there is no recovery mechanism implemented
-	 * and a DLCX can not be performed as the MSC does not know a specific
-	 * endpoint yet. */
-	[] MGCP.receive {
-		setverdict(fail, "Unexpected MGCP message");
-		mtc.stop;
-		}
-	[] as_clear_cmd_compl_disc();
-	}
+	var default ccrel := activate(as_optional_cc_rel(cpars));
+	f_expect_clear(60.0);
+	deactivate(ccrel);
 }
 testcase TC_mo_crcx_ran_reject() runs on MTC_CT {
 	var BSC_ConnHdlr vc_conn;
@@ -1520,10 +1444,6 @@
 friend function f_tc_gsup_cancel(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '22222'H;
-	cpars.mgcp_connection_id_mss := '33333'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
 
 	/* Location Update to make subscriber known */
 	f_perform_lu();
@@ -1741,15 +1661,8 @@
 private function f_tc_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '10004'H;
-	cpars.mgcp_connection_id_mss := '10005'H;
 	cpars.use_osmux := pars.use_osmux;
 
-	/* Note: This is an optional parameter. When the call-agent (MSC) does
-	 * supply a full endpoint name this setting will be overwritten. */
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-
 	f_perform_lu();
 	f_mt_call(cpars);
 }
@@ -1773,11 +1686,6 @@
 private function f_tc_mo_setup_dtmf_dup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '22222'H;
-	cpars.mgcp_connection_id_mss := '33333'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-	cpars.mo_call := true;
 
 	f_perform_lu();
 	f_mo_seq_dtmf_dup(cpars);
@@ -1838,20 +1746,11 @@
 	var MNCC_PDU mncc;
 	var MgcpCommand mgcp_cmd;
 
+	/* Do not respond to the second CRCX */
+	cpars.mgw_conn_2.resp := 0;
+
 	f_perform_lu();
-
-	f_establish_fully();
-	f_create_mncc_expect(hex2str(cpars.called_party));
-	f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
-
-	BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
-	MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
-	cpars.mncc_callref := mncc.u.signal.callref;
-	MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
-
-	/* Drop CRCX */
-	MGCP.receive(tr_CRCX) -> value mgcp_cmd;
+	f_mo_call_establish(cpars);
 
 	var default ccrel := activate(as_optional_cc_rel(cpars));
 
@@ -1872,13 +1771,6 @@
 private function f_tc_lu_and_mt_call_no_dlcx_resp(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '10004'H;
-	cpars.mgcp_connection_id_mss := '10005'H;
-
-	/* Note: This is an optional parameter. When the call-agent (MSC) does
-	 * supply a full endpoint name this setting will be overwritten. */
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
 
 	/* Intentionally disable the CRCX response */
 	cpars.mgw_drop_dlcx := true;
@@ -3107,10 +2999,6 @@
 
 	/* Call parameters taken from f_tc_lu_and_mt_call */
 	var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
-	cpars.mgcp_connection_id_bss := '10004'H;
-	cpars.mgcp_connection_id_mss := '10005'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-	cpars.bss_rtp_port := 1110;
 
 	/* Perform location update */
 	f_perform_lu();
@@ -3190,51 +3078,13 @@
 friend function f_tc_mo_cc_bssmap_clear(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	var MNCC_PDU mncc;
-	var MgcpCommand mgcp_cmd;
+	cpars.ran_clear_when_alerting := true;
 
 	f_perform_lu();
 
-	f_establish_fully();
-	f_create_mncc_expect(hex2str(cpars.called_party));
-	f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
-
-	BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
-	MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
-	cpars.mncc_callref := mncc.u.signal.callref;
-	log("mncc_callref=", cpars.mncc_callref);
-	MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
-
-	MNCC.send(ts_MNCC_ALERT_req(cpars.mncc_callref));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id)));
-	MGCP.receive(tr_CRCX);
-
-	f_sleep(1.0);
-	if (pars.ran_is_geran) {
-		BSSAP.send(ts_BSSMAP_ClearRequest(0));
-	} else {
-		BSSAP.send(ts_RANAP_IuReleaseRequest(ts_RanapCause_om_intervention));
-	}
-
 	var default ccrel := activate(as_optional_cc_rel(cpars));
-
-	if (pars.ran_is_geran) {
-		interleave {
-		[] MNCC.receive(tr_MNCC_REL_ind(?, ?)) { };
-		[] BSSAP.receive(tr_BSSMAP_ClearCommand) {
-			BSSAP.send(ts_BSSMAP_ClearComplete);
-			};
-		}
-	} else {
-		interleave {
-		[] MNCC.receive(tr_MNCC_REL_ind(?, ?)) { };
-		[] BSSAP.receive(tr_RANAP_IuReleaseCommand(?)) {
-			BSSAP.send(ts_RANAP_IuReleaseComplete);
-			};
-		}
-	}
-
+	f_mo_call_establish(cpars);
+	f_expect_clear()
 	deactivate(ccrel);
 
 	f_sleep(1.0);
@@ -3255,10 +3105,6 @@
 
 	/* Call parameters taken from f_tc_lu_and_mt_call */
 	var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
-	cpars.mgcp_connection_id_bss := '10004'H;
-	cpars.mgcp_connection_id_mss := '10005'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-	cpars.bss_rtp_port := 1110;
 
 	/* Perform location update */
 	f_perform_lu();
@@ -5020,13 +4866,6 @@
 
 	var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '10004'H;
-	cpars.mgcp_connection_id_mss := '10005'H;
-
-	/* Note: This is an optional parameter. When the call-agent (MSC) does
-	 * supply a full endpoint name this setting will be overwritten. */
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
 
 	/* Initiate a call via MNCC interface */
 	f_mt_call_initate(cpars);
@@ -5142,11 +4981,6 @@
 private function f_tc_ho_inter_bsc_unknown_cell(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	f_init_handler(pars);
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '22222'H;
-	cpars.mgcp_connection_id_mss := '33333'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-	cpars.mo_call := true;
 
 	f_perform_lu();
 	f_mo_call_establish(cpars);
@@ -5175,25 +5009,20 @@
 private altstep as_mgcp_ack_all_mdcx(CallParameters cpars) runs on BSC_ConnHdlr {
 	var MgcpCommand mgcp_cmd;
 	[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
-			var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_mss, cpars.mgw_rtp_ip_mss,
+			var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
 								hex2str(cpars.mgcp_call_id), "42",
-								cpars.mgw_rtp_port_mss,
+								cpars.mgw_conn_2.mgw_rtp_port,
 								{ int2str(cpars.rtp_payload_type) },
 								{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
 											cpars.rtp_sdp_format)),
 								  valueof(ts_SDP_ptime(20)) }));
-			MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp));
+			MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp));
 			repeat;
 		}
 }
 
 private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '22222'H;
-	cpars.mgcp_connection_id_mss := '33333'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-	cpars.mo_call := true;
 
 	f_init_handler(pars);
 
@@ -5353,11 +5182,6 @@
 
 private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
-	cpars.bss_rtp_port := 1110;
-	cpars.mgcp_connection_id_bss := '22222'H;
-	cpars.mgcp_connection_id_mss := '33333'H;
-	cpars.mgcp_ep := "rtpbridge/1 at mgw";
-	cpars.mo_call := true;
 	var hexstring ho_number := f_gen_msisdn(99999);
 
 	f_init_handler(pars);

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/15938
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: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
Gerrit-Change-Number: 15938
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/20191103/b53e0cc8/attachment.htm>


More information about the gerrit-log mailing list