msc: Rewrite TC_lu_and_mo_call() to be more modular

All relevant parameters are passed in in form of a CallParameters
record, and the bulk of the work has been moved to
BSC_ConnectionHandler.

Change-Id: I932c6c9f7a48b6a1f1ec399e8bba6a413c8bc69e
diff --git a/msc_tests/BSC_ConnectionHandler.ttcn b/msc_tests/BSC_ConnectionHandler.ttcn
index d691d80..8ce1332 100644
--- a/msc_tests/BSC_ConnectionHandler.ttcn
+++ b/msc_tests/BSC_ConnectionHandler.ttcn
@@ -2,7 +2,9 @@
 
 import from General_Types all;
 import from Osmocom_Types all;
+import from Native_Functions all;
 import from GSM_Types all;
+import from IPL4asp_Types all;
 import from SCCPasp_Types all;
 import from BSSAP_Types all;
 import from BSSMAP_Emulation all;
@@ -16,10 +18,13 @@
 
 import from MGCP_Types all;
 import from MGCP_Emulation all;
+import from MGCP_Templates all;
+import from SDP_Types all;
 
 import from MobileL3_Types all;
 import from MobileL3_CommonIE_Types all;
 import from MobileL3_MM_Types all;
+import from MobileL3_CC_Types all;
 import from L3_Templates all;
 
 /* this component represents a single subscriber connection */
@@ -261,6 +266,138 @@
 	/* re-configure MSC behaviour via VTY */
 }
 
+/* parameters related to a (MO?) voice call */
+type record CallParameters {
+	boolean expect_auth,				/* do we expect AUTHENTICATE from network */
+	boolean expect_ciph,				/* do we expect CIPHER MODE from network */
+
+	/* CC related parameters */
+	hexstring called_party,				/* whom are we calling */
+	integer transaction_id optional,		/* which TS 04.08 CC transaction ID to use */
+	BearerCapability_TLV bearer_cap,		/* which bearer capabilities to claim */
+
+	/* MNCC related parameters */
+	uint32_t mncc_callref optional,			/* call reference on the MNCC side */
+	MNCC_bearer_cap mncc_bearer_cap optional,	/* MNCC-side bearer capabilities */
+
+	/* RTP related parameters */
+	HostName bss_rtp_ip optional,			/* BSS Side RTP IP */
+	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 */
+	uint7_t rtp_payload_type,			/* dynamic RTP payload type */
+	charstring rtp_sdp_format,			/* AMR/8000 or the like */
+
+	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 */
+}
+
+template (value) CallParameters t_CallParams(hexstring called, integer tid) := {
+	expect_auth := false,
+	expect_ciph := false,
+	called_party := called,
+	transaction_id := tid,
+	bearer_cap := valueof(ts_Bcap_voice),
+	mncc_callref := omit,
+	mncc_bearer_cap := valueof(ts_MNCC_bcap_voice),
+	bss_rtp_ip := "1.1.1.1",
+	bss_rtp_port := 0,//
+	mss_rtp_ip := omit,
+	mss_rtp_port := omit,
+	rtp_payload_type := 98,
+	rtp_sdp_format := "AMR/8000",
+	mgcp_call_id := omit,
+	mgcp_ep := omit,
+	mgcp_connection_id_bss := '0'H,//
+	mgcp_connection_id_mss := '0'H //
+};
+
+
+function f_mo_call(inout CallParameters cpars)
+runs on BSC_ConnHdlr {
+
+	var MobileIdentityLV mi;
+	var MNCC_PDU mncc;
+	var MgcpCommand mgcp_cmd;
+
+	/* If we have a TMSI, use TMSI instead of IMSI */
+	if (ispresent(g_pars.tmsi)) {
+		mi := valueof(ts_MI_TMSI_LV(g_pars.tmsi));
+	} else {
+		mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+	}
+	f_establish_fully(mi, cpars.expect_auth, cpars.expect_ciph);
+
+	/* Create MNCC and MGCP expect */
+	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)));
+	interleave {
+	[] MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc {
+		cpars.mncc_callref := mncc.u.signal.callref;
+		/* Call Proceeding */
+		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 {
+		cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
+		/* TODO: dynamic EP allocation case */
+		cpars.mgcp_ep := mgcp_cmd.line.ep;
+		var SDP_Message sdp := valueof(ts_SDP(cpars.bss_rtp_ip, cpars.bss_rtp_ip,
+							hex2str(cpars.mgcp_call_id), "42",
+							cpars.bss_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_CRCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_bss, sdp));
+		}
+	}
+
+	/* Alerting */
+	MNCC.send(ts_MNCC_ALERT_req(cpars.mncc_callref));
+	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id)));
+
+	alt {
+	/* FIXME: expect AoIP IP/Port to match what we returned in CRCX_ACK above */
+	[] BSSAP.receive(tr_BSSMAP_AssignmentReq) {
+		var BSSMAP_IE_AoIP_TransportLayerAddress tla;
+		tla := valueof(ts_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.bss_rtp_ip), cpars.bss_rtp_port));
+		BSSAP.send(ts_BSSMAP_AssignmentComplete(omit, tla));
+		}
+	}
+
+	/* Answer. This causes TCH assignment in case of "late assignment" */
+	MNCC.send(ts_MNCC_SETUP_COMPL_req(cpars.mncc_callref));
+
+	f_sleep(3.0);
+
+	/* Hangup by "B" side */
+	MNCC.send(ts_MNCC_DISC_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
+	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
+
+	/* Release of call */
+	MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(42))));
+	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)));
+
+	/* clearing of radio channel */
+	interleave {
+	[] BSSAP.receive(tr_BSSMAP_ClearCommand) {
+		BSSAP.send(ts_BSSMAP_ClearComplete);
+		BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
+		}
+	[] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
+		/* TODO: For one or all connections on EP? */
+		MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
+		f_create_mgcp_delete_ep(cpars.mgcp_ep);
+		}
+	}
+	setverdict(pass);
+}
 
 
 
diff --git a/msc_tests/MSC_Tests.ttcn b/msc_tests/MSC_Tests.ttcn
index 83ad17c..5afa93a 100644
--- a/msc_tests/MSC_Tests.ttcn
+++ b/msc_tests/MSC_Tests.ttcn
@@ -534,60 +534,13 @@
 
 private function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
 	g_pars := pars;
-	f_perform_lu(false, true, true);
+	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;
 
-	f_establish_fully(valueof(ts_MI_IMSI_LV(g_pars.imsi)), false, false);
-
-	var hexstring called := '12345'H;
-	var integer tid := 0;
-	var MNCC_PDU mncc;
-	var MgcpCommand mgcp_cmd;
-	f_create_mncc_expect(hex2str(called));
-	f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
-
-	BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(tid, called)));
-	interleave {
-	[] MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(called)))) -> value mncc {
-		/* FIXME: extract call_id */
-		/* Call Proceeding */
-		MNCC.send(ts_MNCC_CALL_PROC_req(mncc.u.signal.callref, ts_MNCC_bcap_voice));
-		BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(tid)));
-		};
-	[] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
-		var SDP_Message sdp := valueof(ts_SDP("127.0.0.2", "127.0.0.1", "23", "42", 1234,
-							{ "98" },
-							{ valueof(ts_SDP_rtpmap(98, "AMR/8000")),
-							  valueof(ts_SDP_ptime(20)) }));
-		MGCP.send(ts_CRCX_ACK(mgcp_cmd.line.trans_id, '1234'H, sdp));
-		}
-	}
-
-	/* Alerting */
-	MNCC.send(ts_MNCC_ALERT_req(mncc.u.signal.callref));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(tid)));
-
-	BSSAP.receive(tr_BSSMAP_AssignmentReq);
-	BSSAP.send(ts_BSSMAP_AssignmentComplete);
-
-	/* Answer. This causes TCH assignment in case of "late assignment" */
-	MNCC.send(ts_MNCC_SETUP_COMPL_req(mncc.u.signal.callref));
-
-	f_sleep(3.0);
-
-	/* Hangup by "B" side */
-	MNCC.send(ts_MNCC_DISC_req(mncc.u.signal.callref, valueof(ts_MNCC_cause(23))));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(tid)));
-
-	/* Release of call */
-	MNCC.send(ts_MNCC_REL_req(mncc.u.signal.callref, valueof(ts_MNCC_cause(42))));
-	BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(tid)));
-
-	/* clearing of radio channel */
-	BSSAP.receive(tr_BSSMAP_ClearCommand);
-	BSSAP.send(ts_BSSMAP_ClearComplete);
-	BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
-
-	f_sleep(5.0);
+	f_perform_lu(cpars.expect_auth, true, true);
+	f_mo_call(cpars);
 }
 testcase TC_lu_and_mo_call() runs on MTC_CT {
 	var BSC_ConnHdlr vc_conn;
diff --git a/msc_tests/gen_links.sh b/msc_tests/gen_links.sh
index b501c55..4249947 100755
--- a/msc_tests/gen_links.sh
+++ b/msc_tests/gen_links.sh
@@ -75,7 +75,7 @@
 gen_links $DIR $FILES
 
 DIR=../library
-FILES="General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn MNCC_Types.ttcn MNCC_EncDec.cc MNCC_CodecPort.ttcn mncc.h MNCC_Emulation.ttcn Osmocom_VTY_Functions.ttcn "
+FILES="General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn MNCC_Types.ttcn MNCC_EncDec.cc MNCC_CodecPort.ttcn mncc.h MNCC_Emulation.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
 FILES+="IPA_Types.ttcn IPA_Emulation.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc RSL_Types.ttcn GSUP_Types.ttcn GSUP_Emulation.ttcn "
 FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn L3_Templates.ttcn L3_Templates.ttcn "
 FILES+="BSSMAP_Emulation.ttcn BSSAP_CodecPort.ttcn BSSMAP_Templates.ttcn BSSAP_Adapter.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_Emulation.ttcn IPA_Emulation.ttcn "
diff --git a/msc_tests/regen_makefile.sh b/msc_tests/regen_makefile.sh
index 10ec38f..dacd10b 100755
--- a/msc_tests/regen_makefile.sh
+++ b/msc_tests/regen_makefile.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
 
-FILES="*.ttcn SCCP_EncDec.cc  SCTPasp_PT.cc  TCCConversion.cc TCCInterface.cc UD_PT.cc MNCC_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc SDP_EncDec.cc RTP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc RTP_CodecPort_CtrlFunctDef.cc MGCP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc *.c"
+FILES="*.ttcn SCCP_EncDec.cc  SCTPasp_PT.cc  TCCConversion.cc TCCInterface.cc UD_PT.cc MNCC_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc SDP_EncDec.cc RTP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc RTP_CodecPort_CtrlFunctDef.cc MGCP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc Native_FunctionDefs.cc *.c"
 
 ../regen-makefile.sh MSC_Tests.ttcn $FILES