WIP: MSC_Tests: Add SGs testcases

This extens MSC_Tests.ttcn with an initial set of SGs interface test
cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures

In particular the following testcases are added:

- TC_sgsap_reset: isolated reset procedure test
- TC_sgsap_lu: isolated location update with TMSI realloc
- TC_sgsap_lu_imsi_reject: location update, reject case
- TC_sgsap_lu_and_nothing: location update with failed TMSI realloc
- TC_sgsap_expl_imsi_det_eps: detach from EPS serveces
- TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services
- TC_sgsap_paging_rej: isolated paging, reject case
- TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call
- TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable
- TC_sgsap_paging_and_nothing: page, but don't respond
- TC_sgsap_paging_and_lu: check paging followed by an LU
- TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface
- TC_sgsap_mo_sms: mobile originated SMS through SGs Interface
- TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging
- TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging
- TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL)
- TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR)
- TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call
- TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call

Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858
Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d
Related: OS#3645
diff --git a/library/SGsAP_Emulation.ttcn b/library/SGsAP_Emulation.ttcn
index 968bcdd..442cc7c 100644
--- a/library/SGsAP_Emulation.ttcn
+++ b/library/SGsAP_Emulation.ttcn
@@ -32,6 +32,7 @@
 import from Osmocom_Types all;
 import from IPL4asp_Types all;
 import from DNS_Helpers all;
+import from MobileL3_Types all;
 
 type component SGsAP_ConnHdlr {
 	port SGsAP_Conn_PT SGsAP;
@@ -41,7 +42,7 @@
 
 /* port between individual per-connection components and this dispatcher */
 type port SGsAP_Conn_PT message {
-	inout PDU_SGsAP;
+	inout PDU_SGsAP, PDU_ML3_MS_NW, PDU_ML3_NW_MS;
 } with { extension "internal" };
 
 /* represents a single SGsAP Association */
@@ -292,6 +293,8 @@
 
 	while (true) {
 		var SGsAP_ConnHdlr vc_conn;
+		var PDU_ML3_MS_NW l3_mo;
+		var PDU_ML3_NW_MS l3_mt;
 		var template IMSI imsi_t;
 		var hexstring imsi;
 		var SGsAP_RecvFrom mrf;
@@ -305,6 +308,38 @@
 			/* TODO: check which ConnectionID client has allocated + store in table? */
 			SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, msg));
 			}
+		/* DTAP/MobileL3 from client (emulated MS): wrap in SGsAP-UL-UD and send */
+		[] SGsAP_CLIENT.receive(PDU_ML3_MS_NW:?) -> value l3_mo sender vc_conn {
+			var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_mo);
+			imsi := f_imsi_by_comp(vc_conn);
+			msg := valueof(ts_SGsAP_UL_UD(imsi, l3_enc));
+			SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, msg));
+			}
+		[] SGsAP_CLIENT.receive(PDU_ML3_NW_MS:?) -> value l3_mt sender vc_conn {
+			var octetstring l3_enc := enc_PDU_ML3_NW_MS(l3_mt);
+			imsi := f_imsi_by_comp(vc_conn);
+			msg := valueof(ts_SGsAP_DL_UD(imsi, l3_enc));
+			SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, msg));
+			}
+
+		/* DTAP/MobileL3 from MSC/VLR to MS wrapped in SGsAP-DL-UD: Extract, decode, forward */
+		[] SGsAP.receive(tr_SGsAP_RecvFrom_R(tr_SGsAP_DL_UD(?,?))) -> value mrf {
+			var octetstring l3_enc := mrf.msg.sGsAP_DOWNLINK_UNITDATA.nAS_MessageContainer.nAS_MessageContainer;
+			imsi := mrf.msg.sGsAP_DOWNLINK_UNITDATA.iMSI.iMSI.digits;
+			vc_conn := f_comp_by_imsi(imsi);
+			l3_mt := dec_PDU_ML3_NW_MS(l3_enc);
+			SGsAP_CLIENT.send(l3_mt) to vc_conn;
+			}
+		[] SGsAP.receive(tr_SGsAP_RecvFrom_R(tr_SGsAP_UL_UD(?,?))) -> value mrf {
+			var octetstring l3_enc := mrf.msg.sGsAP_UPLINK_UNITDATA.nAS_MessageContainer.nAS_MessageContainer;
+			imsi := mrf.msg.sGsAP_UPLINK_UNITDATA.iMSI.iMSI.digits;
+			l3_mo := dec_PDU_ML3_MS_NW(l3_enc);
+			vc_conn := f_comp_by_imsi(imsi);
+			SGsAP_CLIENT.send(l3_mo) to vc_conn;
+			}
+
+
+		/* any other SGsAP from MSC/VLR */
 		[] SGsAP.receive(tr_SGsAP_RecvFrom_R(?)) -> value mrf {
 			imsi_t := f_SGsAP_get_imsi(mrf.msg);
 			if (isvalue(imsi_t)) {
diff --git a/library/SGsAP_Templates.ttcn b/library/SGsAP_Templates.ttcn
index 9526080..457481e 100644
--- a/library/SGsAP_Templates.ttcn
+++ b/library/SGsAP_Templates.ttcn
@@ -69,7 +69,10 @@
 		return omit;
 	} else if (istemplatekind(digits, "*")) {
 		return *;
+	} else if (istemplatekind(digits, "?")) {
+		return ?;
 	}
+	log("tr_SGsAP_IMSI: ", digits);
 	var template IMSI imsi := {
 		iEI := '00000001'B,
 		lengthIndicator := lengthof(digits)/2 + 1,