mme: Introduce test TC_ue_cell_reselect_eutran_to_geran

Initial bits to be able to test SGSN Context Request+Response emulating
an UE doing cell reselection from 4G to 2G.

Related: OS#6294
Change-Id: I707cb8c6b39c1440db5ccc2f02d08337b38fb564
diff --git a/library/GTP_Templates.ttcn b/library/GTP_Templates.ttcn
index 06ba208..839ed28 100644
--- a/library/GTP_Templates.ttcn
+++ b/library/GTP_Templates.ttcn
@@ -41,6 +41,37 @@
 		/* FIXME */
 	};
 
+	template (value) Cause_gtpc ts_Cause_gtpc(template (value) GTP_Cause cause) := {
+		type_gtpc := '01'O,
+		causevalue := enum2oct1_Cause_gtpc_tmpl(cause)
+	}
+	private function enum2oct1_Cause_gtpc_tmpl(template GTP_Cause inp) return template OCT1
+	{
+		if (istemplatekind(inp, "omit")) {
+			return omit;
+		} else if (istemplatekind(inp, "*")) {
+			return *;
+		} else if (istemplatekind(inp, "?")) {
+			return ?;
+		} else {
+			return int2oct(enum2int(valueof(inp)), 1);
+		}
+	}
+	template (present) Cause_gtpc tr_Cause_gtpc(template (present) GTP_Cause cause) := {
+		type_gtpc := '01'O,
+		causevalue := enum2oct1_Cause_gtpc_tmpl(cause)
+	}
+	function f_tr_Cause_gtpc(template GTP_Cause cause) return
+	template Cause_gtpc {
+		if (istemplatekind(cause, "omit")) {
+			return omit;
+		} else if (istemplatekind(cause, "*")) {
+			return *;
+		} else {
+			return tr_Cause_gtpc(cause);
+		}
+	}
+
 	private function f_oct_or_wc(template integer inp, integer len) return template octetstring {
 		if (istemplatekind(inp, "omit")) {
 			return omit;
@@ -119,6 +150,18 @@
 		restartCounter := restart_counter
 	}
 
+	/* Packet TMSI - 7.7.5 */
+	template (value) PacketTMSI ts_PTMSI(OCT4 ptmsi) := {
+		type_gtpc := '05'O,
+		p_tmsi := ptmsi
+	}
+
+	/* PTMSI Signature - 7.7.9 */
+	template (value) PTMSI_Signature ts_PTMSI_sig(OCT3 ptmsi_sig) := {
+		type_gtpc := '0C'O,
+		ptmsi_Signature := ptmsi_sig
+	}
+
 	/* IMEI(SV) IE TS 29.060 7.7.53 */
 	template (value) IMEISV_gtpc ts_IMEISV(template (value) OCT8 imeisv) := {
 		type_gtpc := '9A'O,
@@ -350,7 +393,7 @@
 		apn_value := apn
 	}
 
-	template (value) GSN_Address_GTPC ts_GsnAddr(octetstring ip_addr) := {
+	template (value) GSN_Address_GTPC ts_GsnAddr(template (value) octetstring ip_addr) := {
 		type_gtpc := '85'O,
 		lengthf := lengthof(ip_addr),
 		addressf := ip_addr
@@ -402,6 +445,29 @@
 		digits := digits,
 		padding := 'F'H
 	}
+	function f_ts_Imsi(template (omit) hexstring digits := omit) return template (omit) IMSI_gtpc {
+		var template (omit) IMSI_gtpc imsi;
+		if (istemplatekind(digits, "omit")) {
+			imsi := omit;
+		} else {
+			imsi := ts_Imsi(valueof(digits));
+		}
+		return imsi;
+	}
+	template (present) IMSI_gtpc tr_Imsi(template (present) hexstring digits) := {
+		type_gtpc := '02'O,
+		digits := digits,
+		padding := 'F'H
+	}
+	function f_tr_Imsi(template hexstring digits := *) return template IMSI_gtpc {
+		if (istemplatekind(digits, "omit")) {
+			return omit;
+		} else if (istemplatekind(digits, "*")) {
+			return *;
+		} else {
+			return tr_Imsi(digits);
+		}
+	}
 
 	function f_ts_RATType(template (omit) OCT1 ratType := omit) return template (omit) RATType {
 		var template (omit) RATType rt;
@@ -417,6 +483,17 @@
 		return rt;
 	}
 
+	template (value) RoutingAreaIdentity ts_RoutingAreaIdentity(template (value) hexstring mcc_digits,
+								    template (value) hexstring mnc_digits,
+								    template (value) OCT2      lac,
+								    template (value) OCT1      rac) := {
+		type_gtpc := '03'O,
+		mcc_digits := mcc_digits,
+		mnc_digits := mnc_digits,
+		lac := lac,
+		rac := rac
+	}
+
 	template (value) GeographicLocationCGI
 	ts_GeographicLocationCGI(template (value) hexstring mcc,
 				 template (value) hexstring mnc,
@@ -869,6 +946,101 @@
 					valueof(ts_DeletePdpRespPDU(cause, pco)), seq)
 	}
 
+	/* SGSN Context Request - 7.5.3 */
+	template (value) GTPC_PDUs ts_SGSNContextReqPDU(template (value) RoutingAreaIdentity rai,
+							template (value) OCT4 teic,
+							template (value) octetstring sgsn_addr_control,
+							template (omit) hexstring imsi := omit,
+							template (value) BIT1 msValidated := '0'B,
+							template (omit) TLLI tlli := omit,
+							template (omit) PacketTMSI ptmsi := omit,
+							template (omit) PTMSI_Signature ptmsi_sig := omit,
+							template (omit) OCT1 rat_type := omit) := {
+		sgsn_ContextRequest := {
+			imsi := f_ts_Imsi(imsi),
+			routingAreaIdentity := rai,
+			tlli := tlli,
+			packetTMSI := ptmsi,
+			ptmsi_Signature := ptmsi_sig,
+			ms_Validated := {
+				type_gtpc := '0D'O,
+				msValidated := msValidated,
+				spare := '1111111'B
+			},
+			teidControlPlane := {
+				type_gtpc := '11'O,
+				teidControlPlane := teic
+			},
+			sgsn_addr_controlPlane := ts_GsnAddr(sgsn_addr_control),
+			alternative_sgsn_addr_controlPlane := omit,
+			sGSN_Number := omit,
+			ratType := f_ts_RATType(rat_type),
+			hopCounter := omit,
+			private_extension_gtpc := omit
+		}
+	}
+	template (value) Gtp1cUnitdata ts_GTPC_SGSNContextReq(GtpPeer peer, uint16_t seq,
+							      template (value) GTPC_PDUs SGSNContextReqPDU) := {
+		peer := peer,
+		gtpc := ts_GTP1C_PDU(sgsnContextRequest, '00000000'O, valueof(SGSNContextReqPDU), seq)
+	}
+
+	/* SGSN Context Response - 7.5.4 */
+	template (present) GTPC_PDUs tr_SGSNContextRespPDU(template (present) GTP_Cause cause := ?,
+							  template hexstring imsi := *) := {
+		sgsn_ContextResponse := {
+			cause := tr_Cause_gtpc(cause),
+			imsi := f_tr_Imsi(imsi),
+			teidControlPlane := *,
+			rabContext := *,
+			radioPrioritySMS := *,
+			radioPriority := *,
+			packetFlowID := *,
+			charging_char := *,
+			mm_Context := *,
+			pdp_Context := *,
+			sgsn_addr_controlPlane := *,
+			pdpContextPriorization := *,
+			radioPriority_LCS := *,
+			mBMS_UE_Context := *,
+			subscribedRFSP_Index := *,
+			rFSP_IndexInUse := *,
+			colocatedGGSN_PGW_FQDN := *,
+			evolvedAllocationRetentionPriorityII := *,
+			extendedCommonFlags := *,
+			ue_network_capability := *,
+			ue_ambr := *,
+			apn_ambr_nsapi := *,
+			signallingPriorityIndication_nsapi := *,
+			higher_bitrates_than_16mbps_flag := *,
+			selectionMode_nsapi := *,
+			localHomeNetworkID_nsapi := *,
+			uE_UsageType := *,
+			extendedCommonFlagsII := *,
+			private_extension_gtpc := *
+		}
+	}
+	template (present) Gtp1cUnitdata tr_GTPC_SGSNContextResp(template (present) GtpPeer peer := ?,
+								 template (present) OCT4 teid := ?,
+								 template (present) GTPC_PDUs SGSNContextRespPDU := ?)
+		:= tr_GTPC_MsgType(peer, sgsnContextResponse, teid, SGSNContextRespPDU);
+
+	/* SGSN Context Acknowledge - 7.5.5 */
+	template (value) GTPC_PDUs ts_SGSNContextAckPDU(template (value) GTP_Cause cause := GTP_CAUSE_REQUEST_ACCEPTED) := {
+		sgsn_ContextAcknowledge := {
+			cause := ts_Cause_gtpc(cause),
+			teidDataII := omit,
+			sgsn_AddressForUserTraffic := omit,
+			sgsn_Number := omit,
+			nodeIdentifier  := omit,
+			private_extension_gtpc := omit
+		}
+	}
+	template (value) Gtp1cUnitdata ts_GTPC_SGSNContextAck(GtpPeer peer, uint16_t seq,
+							      template (value) GTPC_PDUs SGSNContextAckPDU := ts_SGSNContextAckPDU(GTP_CAUSE_REQUEST_ACCEPTED)) := {
+		peer := peer,
+		gtpc := ts_GTP1C_PDU(sgsnContextAcknowledge, '00000000'O, valueof(SGSNContextAckPDU), seq)
+	}
 
 	/* GTP-C RIM */