msc_tests: Initial skeleton for osmo-msc testing over SCCP/M3UA
diff --git a/msc_tests/MSC_Tests.ttcn b/msc_tests/MSC_Tests.ttcn
new file mode 100644
index 0000000..adb9453
--- /dev/null
+++ b/msc_tests/MSC_Tests.ttcn
@@ -0,0 +1,321 @@
+module MSC_Tests {
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from M3UA_Types all;
+import from M3UA_Emulation all;
+
+import from MTP3asp_Types all;
+import from MTP3asp_PortType all;
+
+import from SCCPasp_Types all;
+import from SCCP_Types all;
+import from SCCP_Emulation all;
+
+import from SCTPasp_Types all;
+import from SCTPasp_PortType all;
+
+import from BSSAP_Types all;
+
+type component MTC_CT {
+	/* M3UA emulation component */
+	var M3UA_CT vc_M3UA;
+	/* SCCP emulation component */
+	var SCCP_CT vc_SCCP;
+	/* test port to SCCP emulation */
+	port SCCPasp_PT SCCP;
+
+	var octetstring g_sio;
+	var MSC_SCCP_MTP3_parameters g_sccp_pars;
+	var SCCP_PAR_Address g_sccp_addr_own, g_sccp_addr_peer;
+
+	var boolean g_initialized := false;
+}
+
+modulepar {
+	charstring mp_sccp_service_type := "mtp3_itu";
+
+	SCTP_Association_Address mp_sctp_addr := { 22905, "127.0.0.1", 2905, "127.0.0.1" };
+	integer mp_own_pc := 196;
+	integer mp_own_ssn := 254;
+
+	integer mp_peer_pc := 185;	/* 0.23.1 */
+	integer mp_peer_ssn := 254;
+}
+
+
+/* construct a SCCP_PAR_Address with just PC + SSN and no GT */
+template (value) SCCP_PAR_Address ts_SccpAddr_PC_SSN(integer pc, integer ssn) := {
+	addressIndicator := {
+		pointCodeIndic := '1'B,
+		ssnIndicator := '1'B,
+		globalTitleIndic := '0000'B,
+		routingIndicator := '1'B
+	},
+	signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, '83'O),
+	//signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, g_sio),
+	subsystemNumber := ssn,
+	globalTitle := omit
+}
+
+function init_pars() runs on MTC_CT {
+	g_sio := '83'O;
+	g_sccp_pars := {
+		sio := {
+			ni := substr(oct2bit(g_sio),0,2),
+			prio := substr(oct2bit(g_sio),2,2),
+			si := substr(oct2bit(g_sio),4,4)
+		},
+		opc := mp_own_pc,
+		dpc := mp_peer_pc,
+		sls := 0,
+		sccp_serviceType := mp_sccp_service_type,
+		ssn := mp_own_ssn
+	};
+	g_sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(mp_own_pc, mp_own_ssn));
+	g_sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(mp_peer_pc, mp_peer_ssn));
+}
+
+function init() runs on MTC_CT {
+
+	if (g_initialized == true) {
+		return;
+	}
+	g_initialized := true;
+
+	init_pars();
+
+	/* Create components */
+	vc_M3UA := M3UA_CT.create;
+	vc_SCCP := SCCP_CT.create;
+
+	/* connect system SCTP port to M3UA lower side */
+	map(vc_M3UA:SCTP_PORT, system:sctp);
+
+	/* connect MTP3 service provider to SCCP MTP3 port */
+	connect(vc_M3UA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT);
+
+	/* connect test suite to SCCP service provider port */
+	connect(self:SCCP, vc_SCCP:SCCP_SP_PORT);
+
+	vc_M3UA.start(f_M3UA_Emulation(mp_sctp_addr));
+	vc_SCCP.start(SCCPStart(g_sccp_pars));
+
+}
+
+function terminate() runs on MTC_CT {
+
+	disconnect(self:SCCP, vc_SCCP:SCCP_SP_PORT);
+	disconnect(vc_M3UA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT);
+	unmap(vc_M3UA:SCTP_PORT, system:sctp);
+
+	all component.stop;
+
+	self.stop;
+}
+
+testcase TC_nothing() runs on MTC_CT {
+	init();
+
+	timer T := 30.0;
+	T.start;
+	T.timeout;
+
+}
+
+template PDU_BSSAP ts_BSSAP_BSSMAP := {
+	discriminator := '0'B,
+	spare := '0000000'B,
+	dlci := omit,
+	lengthIndicator := 0,	/* overwritten by codec */
+	pdu := ?
+}
+
+template PDU_BSSAP tr_BSSAP_BSSMAP := {
+	discriminator := '0'B,
+	spare := '0000000'B,
+	dlci := omit,
+	lengthIndicator := ?,
+	pdu := {
+		bssmap := ?
+	}
+}
+
+
+type integer BssmapCause;
+
+template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
+	elementIdentifier := '04'O,
+	lengthIndicator := 0,
+	causeValue := int2bit(val, 7),
+	extensionCauseValue := '0'B,
+	spare1 := omit
+}
+
+template (value) PDU_BSSAP ts_BSSMAP_Reset(BssmapCause cause) modifies ts_BSSAP_BSSMAP := {
+	pdu := {
+		bssmap := {
+			reset := {
+				messageType := '30'O,
+				cause := ts_BSSMAP_IE_Cause(cause),
+				a_InterfaceSelectorForReset := omit
+			}
+		}
+	}
+}
+
+template (value) PDU_BSSAP ts_BSSMAP_ResetAck modifies ts_BSSAP_BSSMAP := {
+	pdu := {
+		bssmap := {
+			resetAck := {
+				messageType := '31'O,
+				a_InterfaceSelectorForReset := omit
+			}
+		}
+	}
+}
+
+template PDU_BSSAP tr_BSSMAP_ResetAck modifies tr_BSSAP_BSSMAP := {
+	pdu := {
+		bssmap := {
+			resetAck := {
+				messageType := '31'O,
+				a_InterfaceSelectorForReset := *
+			}
+		}
+	}
+}
+
+template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
+	elementIdentifier := '05'O,
+	lengthIndicator := 0,
+	cellIdentifierDiscriminator := '0000'B,
+	spare1_4 := '0000'B,
+	cellIdentification := ?
+}
+
+type uint16_t BssmapLAC;
+type uint16_t BssmapCI;
+
+/*
+template BSSMAP_IE_CellIdentifier ts_CellId_CGI(mcc, mnc, lac, ci)
+modifies ts_BSSMAP_IE_CellID := {
+	cellIdentification := {
+		cI_LAC_CGI := {
+			mnc_mcc := FIXME,
+			lac := int2oct(lac, 2),
+			ci := int2oct(ci, 2)
+		}
+	}
+}
+*/
+
+template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
+modifies ts_BSSMAP_IE_CellID := {
+	cellIdentification := {
+		cI_LAC_CI := {
+			lac := int2oct(lac, 2),
+			ci := int2oct(ci, 2)
+		}
+	}
+}
+
+template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
+modifies ts_BSSMAP_IE_CellID := {
+	cellIdentification := {
+		cI_CI := int2oct(ci, 2)
+	}
+}
+
+template BSSMAP_IE_CellIdentifier ts_CellId_none
+modifies ts_BSSMAP_IE_CellID := {
+	cellIdentification := {
+		cI_noCell := ''O
+	}
+}
+
+
+template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
+	elementIdentifier := '17'O,
+	lengthIndicator := 0,
+	layer3info := l3info
+}
+
+template PDU_BSSAP ts_BSSMAP_ComplL3(BSSMAP_IE_CellIdentifier cell_id, octetstring l3_info)
+modifies ts_BSSAP_BSSMAP := {
+	pdu := {
+		bssmap := {
+			completeLayer3Information := {
+				messageType := '57'O,
+				cellIdentifier := cell_id,
+				layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
+				chosenChannel := omit,
+				lSAIdentifier := omit,
+				aPDU := omit,
+				codecList := omit,
+				redirectAttemptFlag := omit,
+				sendSequenceNumber := omit,
+				iMSI := omit
+			}
+		}
+	}
+}
+
+template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_IE_CellIdentifierList cid_list)
+modifies ts_BSSAP_BSSMAP := {
+	pdu := {
+		bssmap := {
+			handoverRequired := {
+				messageType := '11'O,
+				cause := ts_BSSMAP_IE_Cause(cause),
+				responseRequest := omit,
+				cellIdentifierList := cid_list,
+				circuitPoolList := omit,
+				currentChannelType1 := omit,
+				speechVersion := omit,
+				queueingIndicator := omit,
+				oldToNewBSSInfo := omit,
+				sourceToTargetRNCTransparentInfo := omit,
+				sourceToTargetRNCTransparentInfoCDMA := omit,
+				gERANClassmark := omit,
+				talkerPriority := omit,
+				speechCodec := omit,
+				cSG_Identifier := omit
+			}
+		}
+	}
+}
+
+//	enc_PDU_BSSAP
+
+function f_send_BSSAP_UNITDATA(template PDU_BSSAP bssap) runs on MTC_CT {
+	SCCP.send(t_ASP_N_UNITDATA_req(g_sccp_addr_peer, g_sccp_addr_own, '00000001'B, '00000001'B,
+					enc_PDU_BSSAP(valueof(bssap)), omit))
+}
+
+testcase TC_reset() runs on MTC_CT {
+	init();
+
+	timer T := 2.0;
+	T.start;
+	T.timeout;
+
+	f_send_BSSAP_UNITDATA(ts_BSSMAP_Reset(0));
+	T.start;
+	alt {
+		//[] SCCP.receive(tr_BSSMAP_ResetAck) { }
+		[] T.timeout { setverdict(fail); }
+	}
+
+	terminate();
+}
+
+
+control {
+	execute( TC_reset() );
+	execute( TC_nothing() );
+}
+
+
+}
diff --git a/msc_tests/gen_links.sh b/msc_tests/gen_links.sh
new file mode 100755
index 0000000..33b564d
--- /dev/null
+++ b/msc_tests/gen_links.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+BASEDIR=~/projects/git
+
+gen_links() {
+	DIR=$1
+	FILES=$*
+	for f in $FILES; do
+		echo "Linking $f"
+		ln -sf $DIR/$f $f
+	done
+}
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc  UD_PT.hh  UD_PortType.ttcn  UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.ProtocolModules.M3UA/src
+FILES="M3UA_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.TestPorts.SCTPasp/src
+FILES="SCTPasp_PT.cc  SCTPasp_PT.hh  SCTPasp_PortType.ttcn  SCTPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA Emulation
+DIR=../MTP3asp_CNL113337/src
+FILES="MTP3asp_PortType.ttcn  MTP3asp_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=../M3UA_CNL113537/src
+FILES="M3UA_Emulation.ttcn"
+gen_links $DIR $FILES
+
+DIR=../SCCP_CNL113341/src
+FILES="SCCP_Emulation.ttcn  SCCP_EncDec.cc  SCCP_Mapping.ttcnpp  SCCP_Types.ttcn  SCCPasp_Types.ttcn"
+gen_links $DIR $FILES
+ln -s SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn
+
+DIR=$BASEDIR/titan.ProtocolModules.BSSMAP_v11.2.0/src
+FILES="BSSAP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
+FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn"
+gen_links $DIR $FILES
+
+
+DIR=../library
+FILES="General_Types.ttcn Osmocom_Types.ttcn"
+gen_links $DIR $FILES
diff --git a/msc_tests/regen_makefile.sh b/msc_tests/regen_makefile.sh
new file mode 100755
index 0000000..9b1a52d
--- /dev/null
+++ b/msc_tests/regen_makefile.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+FILES="*.ttcn SCCP_EncDec.cc  SCTPasp_PT.cc  TCCConversion.cc TCCInterface.cc"
+
+ttcn3_makefilegen -l -f MSC_Tests.ttcn $FILES
+sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile
+sed -i -e 's/LDFLAGS = /LDFLAGS = -L \/usr\/lib\/titan /' Makefile
+#sed -i -e 's/TTCN3_LIB = ttcn3-parallel/TTCN3_LIB = ttcn3/' Makefile
+sed -i -e 's/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include -I\/usr\/include\/titan/' Makefile