GGSN_Tests: Implement GTP-U ping/pong response
diff --git a/ggsn_tests/GGSN_Tests.ttcn b/ggsn_tests/GGSN_Tests.ttcn
index 0704b22..10f6a86 100644
--- a/ggsn_tests/GGSN_Tests.ttcn
+++ b/ggsn_tests/GGSN_Tests.ttcn
@@ -270,14 +270,87 @@
 								sgsn_ip_data, msisdn)))
 	}
 
+	/* GTP-U */
+
+	template PDU_GTPU tr_GTP1U_PDU(template OCT1 msg_type, template OCT4 teid) := {
+		pn_bit := ?,
+		s_bit := ?,
+		e_bit := ?,
+		spare := ?,
+		/* Protocol Type flag (PT) shall be set to '1' in GTP */
+		pt := '1'B,
+		/* Version shall be set to decimal 1 ('001'). */
+		version := '001'B,
+		messageType := msg_type,
+		lengthf := ?,
+		teid := teid,
+		opt_part := *,
+		gtpu_IEs := ?
+	}
+
+	/* generalized GTP-U send template */
+	template PDU_GTPU ts_GTP1U_PDU(OCT1 msg_type, OCT4 teid, GTPU_IEs ies,
+					template GTPU_Header_optional_part opt := omit) := {
+		/* N-PDU Number flag (PN): the GTP-U header contains a meaningful N-PDU Number field if the PN
+		 * flag is set to 1. */
+		pn_bit := '0'B,	/* we assume the encoder overwrites this if an optional part is given */
+		/* If the Sequence Number flag (S) is set to '1' the sequence number field is present and
+		 * meaningful otherwise it is set to '0'. For GTP-U messages Echo Request, Echo Response,
+		 * Error Indication and Supported Extension Headers Notification, the S flag shall be set to '1'. */
+		s_bit := '0'B, 	/* we assume the encoder overwrites this if an optional part is given */
+		/* Extension header presence */
+		e_bit := '0'B,
+		spare := '0'B,
+		/* Protocol Type flag (PT) shall be set to '1' in GTP */
+		pt := '1'B,
+		/* Version shall be set to decimal 1 ('001'). */
+		version := '001'B,
+		messageType := msg_type,
+		lengthf := 0,	/* we assume encoder overwrites this */
+		teid := teid,
+		opt_part := opt,
+		gtpu_IEs := ies
+	}
+
+	template Gtp1uUnitdata tr_GTPU_MsgType(template GtpPeer peer, template OCT1 msg_type, template OCT4 teid) := {
+		peer := peer,
+		gtpu := tr_GTP1U_PDU(msg_type, teid)
+	}
+
+
+	/* template matching reception of GTP-C echo-request */
+	template Gtp1uUnitdata tr_GTPU_PING(template GtpPeer peer) := tr_GTPU_MsgType(peer, echoRequest, '00000000'O);
+
+	template GTPU_IEs ts_UEchoRespPDU(OCT1 restart_counter) := {
+		echoResponse_IEs := {
+			recovery_gtpu := {
+				type_gtpu := '00'O, /* we assume encoder fixes? */
+				restartCounter := restart_counter
+			},
+			private_extension_gtpu := omit
+		}
+	}
+
+	/* master template for sending a GTP-U echo response */
+	template Gtp1uUnitdata ts_GTPU_PONG(GtpPeer peer, OCT1 rest_ctr) := {
+		peer := peer,
+		gtpu := ts_GTP1U_PDU(echoResponse, '00000000'O, valueof(ts_UEchoRespPDU(rest_ctr)))
+	}
+
+	template PDU_GTPU ts_GTP1U_GPDU(OCT4 teid, octetstring data) :=
+				ts_GTP1U_PDU('FF'O, teid, { g_PDU_IEs := { data := data }});
+
 	/* Altstep implementing responses to any incoming echo requests */
 	altstep pingpong() runs on GT_CT {
 		var Gtp1cUnitdata ud;
+		var Gtp1uUnitdata udu;
 		[] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
 			GTPC.send(ts_GTPC_PONG(ud.peer, '00'O));
 			repeat;
 		};
-		//[] GTPU.receive(tr_GTP_PING(?)) {};
+		[] GTPU.receive(tr_GTPU_PING(?)) -> value udu {
+			GTPU.send(ts_GTPU_PONG(udu.peer, '00'O));
+		};
 		[] T_default.timeout { setverdict(fail); };
 	}