Change in osmo-ttcn3-hacks[master]: Add GTPv2_Emulation component

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Sun Apr 19 17:20:45 UTC 2020


laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/17867 )


Change subject: Add GTPv2_Emulation component
......................................................................

Add GTPv2_Emulation component

Change-Id: If73aa453e44ebf28032c60d207feb03e8061dc0c
---
M deps/Makefile
A library/GTPv2_Emulation.ttcn
M library/GTPv2_Templates.ttcn
M library/General_Types.ttcn
M library/Osmocom_Types.ttcn
5 files changed, 1,197 insertions(+), 11 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/67/17867/1

diff --git a/deps/Makefile b/deps/Makefile
index 65958ae..977beba 100644
--- a/deps/Makefile
+++ b/deps/Makefile
@@ -59,7 +59,7 @@
 			titan.ProtocolModules.NAS_EPS_15.2.0.1 \
 			titan.ProtocolModules.NS_v7.3.0 \
 			titan.ProtocolModules.SGsAP_13.2.0 \
-			titan.ProtocolModules.SNDCP_v7.0.0 \
+			titan.ProtocolModules.SNDCP_v7.0.0
 
 OSMOGITHUB_REPOS=	titan.TestPorts.SCTPasp \
 			titan.TestPorts.MTP3asp \
@@ -69,7 +69,8 @@
 
 OSMOGIT_REPOS=		titan.ProtocolModules.MAP \
 			titan.ProtocolModules.BSSMAP \
-			titan.TestPorts.USB
+			titan.TestPorts.USB \
+			osmo-uecups
 
 ALL_REPOS=$(ECLIPSEGITHUB_REPOS) $(ECLIPSEGIT2_REPOS) $(OSMOGITHUB_REPOS) $(OSMOGIT_REPOS)
 
@@ -125,6 +126,7 @@
 titan.TestPorts.UDPasp_commit=			c20d77a34f288dd70dd4aaa30e520778876e9336
 titan.TestPorts.UNIX_DOMAIN_SOCKETasp_commit=	R.2.A-8-g7ec4fe0
 titan.TestPorts.USB_commit=			master
+osmo-uecups_commit=				master
 
 all: $(foreach dir,$(ALL_REPOS),$(dir)/update)
 clean: $(foreach dir,$(ALL_REPOS),$(dir)/clean)
diff --git a/library/GTPv2_Emulation.ttcn b/library/GTPv2_Emulation.ttcn
new file mode 100644
index 0000000..4930d52
--- /dev/null
+++ b/library/GTPv2_Emulation.ttcn
@@ -0,0 +1,531 @@
+/* GTPv2 Emulation in TTCN-3
+ *
+ * (C) 2018-2020 Harald Welte <laforge at gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module GTPv2_Emulation {
+
+import from IPL4asp_Types all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from GTPv2_Types all;
+import from GTPv2_CodecPort all;
+import from GTPv2_CodecPort_CtrlFunct all;
+
+import from UECUPS_Types all;
+import from UECUPS_CodecPort all;
+import from UECUPS_CodecPort_CtrlFunct all;
+
+/***********************************************************************
+ * Main Emulation Component
+ ***********************************************************************/
+
+modulepar {
+	charstring mp_uecups_host := "127.0.0.1";
+	integer mp_uecups_port := UECUPS_SCTP_PORT;
+};
+
+const integer GTP2C_PORT := 2123;
+const integer GTP1U_PORT := 2152;
+
+type record Gtp2EmulationCfg {
+	HostName gtpc_bind_ip,
+	IPL4asp_Types.PortNumber gtpc_bind_port,
+	HostName gtpc_remote_ip,
+	IPL4asp_Types.PortNumber gtpc_remote_port,
+	//HostName gtpu_bind_ip,
+	//PortNumber gtpu_bind_port,
+	boolean sgw_role,
+	boolean use_gtpu_daemon
+};
+
+type component GTPv2_Emulation_CT {
+	/* Communication with underlying GTP CodecPort */
+	port GTPv2C_PT GTP2C;
+
+	/* Control port to GTP-U Daemon */
+	port UECUPS_CODEC_PT UECUPS;
+
+	/* Communication with Clients */
+	port GTP2EM_PT TEID0;
+	port GTP2EM_PT CLIENT;
+	port GTP2EM_PROC_PT CLIENT_PROC;
+
+	/* Configuration by the user */
+	var Gtp2EmulationCfg g_gtp2_cfg;
+
+	/* State */
+	var GtpPeer g_peer;
+	var integer g_gtp2c_id;
+	var OCT1 g_restart_ctr;
+	var uint16_t g_c_seq_nr;
+	var TidTableRec TidTable[256];
+	var ImsiTableRec ImsiTable[256];
+	var PidTableRec	PidTable[256];
+	var integer g_uecups_conn_id;
+};
+
+type record TidTableRec {
+	OCT4 teid,
+	GTP2_ConnHdlr vc_conn
+};
+
+type record ImsiTableRec {
+	hexstring imsi,
+	GTP2_ConnHdlr vc_conn
+};
+
+type record PidTableRec {
+	/* process ID of the running process */
+	integer pid,
+	/* component that started it */
+	GTP2_ConnHdlr vc_conn
+};
+
+private function f_comp_by_teid(OCT4 teid) runs on GTPv2_Emulation_CT return GTP2_ConnHdlr {
+	var integer i;
+	for (i := 0; i < sizeof(TidTable); i := i+1) {
+		if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) {
+			return TidTable[i].vc_conn;
+		}
+	}
+	setverdict(fail, "No Component for TEID ", teid);
+	mtc.stop;
+}
+
+private function f_comp_by_imsi(hexstring imsi) runs on GTPv2_Emulation_CT return GTP2_ConnHdlr {
+	var integer i;
+	for (i := 0; i < sizeof(ImsiTable); i := i+1) {
+		if (isbound(ImsiTable[i].imsi) and ImsiTable[i].imsi == imsi) {
+			return ImsiTable[i].vc_conn;
+		}
+	}
+	setverdict(fail, "No Component for IMSI ", imsi);
+	mtc.stop;
+}
+
+private function f_comp_by_pid(integer pid) runs on GTPv2_Emulation_CT return GTP2_ConnHdlr {
+	var integer i;
+	for (i := 0; i < sizeof(PidTable); i := i+1) {
+		if (isbound(PidTable[i].pid) and PidTable[i].pid == pid) {
+			/* fixme: remove */
+			return PidTable[i].vc_conn;
+		}
+	}
+	setverdict(fail, "No Component for PID ", pid);
+	mtc.stop;
+}
+
+private function f_tid_tbl_add(OCT4 teid, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT {
+	var integer i;
+	for (i := 0; i < sizeof(TidTable); i := i+1) {
+		if (not isbound(TidTable[i].teid)) {
+			TidTable[i].teid := teid;
+			TidTable[i].vc_conn := vc_conn;
+			return;
+		}
+	}
+	testcase.stop("No Space in TidTable for ", teid);
+}
+
+private function f_imsi_tbl_add(hexstring imsi, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT {
+	var integer i;
+	for (i := 0; i < sizeof(ImsiTable); i := i+1) {
+		if (not isbound(ImsiTable[i].imsi)) {
+			ImsiTable[i].imsi := imsi;
+			ImsiTable[i].vc_conn := vc_conn;
+			return;
+		}
+	}
+	testcase.stop("No Space in IMSI Table for ", imsi);
+}
+
+private function f_pid_tbl_add(integer pid, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT {
+	var integer i;
+	for (i := 0; i < sizeof(PidTable); i := i+1) {
+		if (not isbound(PidTable[i].pid)) {
+			PidTable[i].pid := pid;
+			PidTable[i].vc_conn := vc_conn;
+			return;
+		}
+	}
+	testcase.stop("No Space in PID Table for ", pid);
+}
+
+
+/* allocate an unused local teid */
+private function f_alloc_teid() runs on GTPv2_Emulation_CT return OCT4 {
+	var OCT4 teid;
+	var integer i, j;
+	for (i := 0; i < 100; i := i+1) {
+		teid := f_rnd_octstring(4);
+		for (j := 0; j < sizeof(TidTable); j := j+1) {
+			if (isbound(TidTable) and TidTable[i].teid == teid) {
+				continue;
+			}
+		}
+		/* we iterated over all entries and found no match: great! */
+		return teid;
+	}
+	testcase.stop("Cannot find unused TEID after ", i, " attempts");
+}
+
+/* obtain the IMSI from a GTPv2C PDU, if there is any IMSI contained. The way how the TITAN
+ * GTPv2 decoders are structured (explict IE members rather than a list/set of generic IE structures)
+ * doesn't make this easy, but requires lots of boilerplate code.  Oh well.. */
+function f_gtp2c_extract_imsi(PDU_GTPCv2 gtp) return template (omit) hexstring {
+	if (ischosen(gtp.gtpcv2_pdu.createSessionRequest)) {
+		if (ispresent(gtp.gtpcv2_pdu.createSessionRequest.iMSI)) {
+			return gtp.gtpcv2_pdu.createSessionRequest.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.downlinkDataNotification)) {
+		if (ispresent(gtp.gtpcv2_pdu.downlinkDataNotification.iMSI)) {
+			return gtp.gtpcv2_pdu.downlinkDataNotification.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.downlinkDataNotificationAcknowledgement)) {
+		if (ispresent(gtp.gtpcv2_pdu.downlinkDataNotificationAcknowledgement.iMSI)) {
+			return gtp.gtpcv2_pdu.downlinkDataNotificationAcknowledgement.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.downlinkDataNotificationFailureIndication)) {
+		if (ispresent(gtp.gtpcv2_pdu.downlinkDataNotificationFailureIndication.iMSI)) {
+			return gtp.gtpcv2_pdu.downlinkDataNotificationFailureIndication.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.createIndirectDataForwardingTunnelRequest)) {
+		if (ispresent(gtp.gtpcv2_pdu.createIndirectDataForwardingTunnelRequest.iMSI)) {
+			return gtp.gtpcv2_pdu.createIndirectDataForwardingTunnelRequest.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.stopPagingIndication)) {
+		if (ispresent(gtp.gtpcv2_pdu.stopPagingIndication.iMSI)) {
+			return gtp.gtpcv2_pdu.stopPagingIndication.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.forwardRelocationRequest)) {
+		if (ispresent(gtp.gtpcv2_pdu.forwardRelocationRequest.iMSI)) {
+			return gtp.gtpcv2_pdu.forwardRelocationRequest.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.contextRequest)) {
+		if (ispresent(gtp.gtpcv2_pdu.contextRequest.iMSI)) {
+			return gtp.gtpcv2_pdu.contextRequest.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.identificationResponse)) {
+		if (ispresent(gtp.gtpcv2_pdu.identificationResponse.iMSI)) {
+			return gtp.gtpcv2_pdu.identificationResponse.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.changeNotificationRequest)) {
+		if (ispresent(gtp.gtpcv2_pdu.changeNotificationRequest)) {
+			return gtp.gtpcv2_pdu.changeNotificationRequest.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.changeNotificationResponse)) {
+		if (ispresent(gtp.gtpcv2_pdu.changeNotificationResponse.iMSI)) {
+			return gtp.gtpcv2_pdu.changeNotificationResponse.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.relocationCancelRequest)) {
+		if (ispresent(gtp.gtpcv2_pdu.relocationCancelRequest.iMSI)) {
+			return gtp.gtpcv2_pdu.relocationCancelRequest.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.uE_RegistrationQueryRequest)) {
+		if (ispresent(gtp.gtpcv2_pdu.uE_RegistrationQueryRequest.iMSI)) {
+			return gtp.gtpcv2_pdu.uE_RegistrationQueryRequest.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.uE_RegistrationQueryResponse)) {
+		if (ispresent(gtp.gtpcv2_pdu.uE_RegistrationQueryResponse.iMSI)) {
+			return gtp.gtpcv2_pdu.uE_RegistrationQueryResponse.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.suspendNotification)) {
+		if (ispresent(gtp.gtpcv2_pdu.suspendNotification.iMSI)) {
+			return gtp.gtpcv2_pdu.suspendNotification.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.resumeNotification)) {
+		if (ispresent(gtp.gtpcv2_pdu.resumeNotification.iMSI)) {
+			return gtp.gtpcv2_pdu.resumeNotification.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.cSPagingIndication)) {
+		if (ispresent(gtp.gtpcv2_pdu.cSPagingIndication.iMSI)) {
+			return gtp.gtpcv2_pdu.cSPagingIndication.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.pGW_DownlinkTriggeringNotification)) {
+		if (ispresent(gtp.gtpcv2_pdu.pGW_DownlinkTriggeringNotification.iMSI)) {
+			return gtp.gtpcv2_pdu.pGW_DownlinkTriggeringNotification.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.pGW_DownlinkTriggeringAcknowledge)) {
+		if (ispresent(gtp.gtpcv2_pdu.pGW_DownlinkTriggeringAcknowledge.iMSI)) {
+			return gtp.gtpcv2_pdu.pGW_DownlinkTriggeringAcknowledge.iMSI.iMSI_Value;
+		}
+	} else if (ischosen(gtp.gtpcv2_pdu.traceSessionActivation)) {
+		if (ispresent(gtp.gtpcv2_pdu.traceSessionActivation.iMSI)) {
+			return gtp.gtpcv2_pdu.traceSessionActivation.iMSI.iMSI_Value;
+		}
+	}
+	return omit;
+}
+
+private template (value) SctpTuple ts_SCTP(template (omit) integer ppid := omit) := {
+	sinfo_stream := omit,
+	sinfo_ppid := ppid,
+	remSocks := omit,
+	assocId := omit
+};
+
+function tr_UECUPS_RecvFrom_R(template PDU_UECUPS msg)
+runs on GTPv2_Emulation_CT return template UECUPS_RecvFrom {
+	var template UECUPS_RecvFrom mrf := {
+		connId := g_uecups_conn_id,
+		remName := ?,
+		remPort := ?,
+		locName := ?,
+		locPort := ?,
+		msg := msg
+	}
+	return mrf;
+}
+
+
+private template PortEvent tr_SctpAssocChange := {
+	sctpEvent := {
+		sctpAssocChange := ?
+	}
+}
+private template PortEvent tr_SctpPeerAddrChange := {
+	sctpEvent := {
+		sctpPeerAddrChange := ?
+	}
+}
+
+private function f_uecups_xceive(template (value) PDU_UECUPS tx,
+				template PDU_UECUPS rx_t := ?)
+runs on GTPv2_Emulation_CT  return PDU_UECUPS {
+	timer T := 10.0;
+	var UECUPS_RecvFrom mrf;
+
+	UECUPS.send(t_UECUPS_Send(g_uecups_conn_id, tx));
+	alt {
+	[] UECUPS.receive(tr_UECUPS_RecvFrom_R(rx_t)) -> value mrf { }
+	[] UECUPS.receive(tr_SctpAssocChange) { repeat; }
+	[] UECUPS.receive(tr_SctpPeerAddrChange)  { repeat; }
+	[] T.timeout {
+		setverdict(fail, "Timeout waiting for ", rx_t);
+		mtc.stop;
+		}
+	}
+	return mrf.msg;
+}
+
+private function f_init(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
+	var Result res;
+
+	map(self:GTP2C, system:GTP2C);
+	res := GTPv2_CodecPort_CtrlFunct.f_IPL4_listen(GTP2C, cfg.gtpc_bind_ip,
+						     cfg.gtpc_bind_port, {udp:={}});
+	g_gtp2c_id := res.connId;
+
+	g_restart_ctr := f_rnd_octstring(1);
+	g_c_seq_nr := f_rnd_int(65535);
+	g_gtp2_cfg := cfg;
+	g_peer := {
+		connId := g_gtp2c_id,
+		remName := g_gtp2_cfg.gtpc_remote_ip,
+		remPort := g_gtp2_cfg.gtpc_remote_port
+	}
+
+	if (g_gtp2_cfg.use_gtpu_daemon) {
+		map(self:UECUPS, system:UECUPS);
+		res := UECUPS_CodecPort_CtrlFunct.f_IPL4_connect(UECUPS, mp_uecups_host, mp_uecups_port, "", -1, -1, { sctp := valueof(ts_SCTP) });
+		if (not ispresent(res.connId)) {
+			setverdict(fail, "Could not connect UECUPS socket, check your configuration");
+			testcase.stop;
+		}
+		g_uecups_conn_id := res.connId;
+
+		/* clear all tunnel state in the daemon at start */
+		f_uecups_xceive({reset_all_state := {}}, {reset_all_state_res:=?});
+	}
+
+	/* make sure we always pass incoming UECUPS indications whenever receiving fom the UECUPS port */
+	activate(as_uecups_ind());
+}
+
+private altstep as_uecups_ind() runs on GTPv2_Emulation_CT {
+var UECUPS_RecvFrom rx;
+var GTP2_ConnHdlr vc_conn;
+/* handle incoming program_term_ind; dispatch to whatever component started the process */
+[] UECUPS.receive(tr_UECUPS_RecvFrom_R({program_term_ind:=?})) -> value rx {
+	vc_conn := f_comp_by_pid(rx.msg.program_term_ind.pid);
+	CLIENT.send(rx.msg.program_term_ind) to vc_conn;
+	/* FIXME: remove from table */
+	repeat;
+	}
+}
+
+function main(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
+	var Gtp2cUnitdata g2c_ud;
+	var PDU_GTPCv2 g2c;
+	var GTP2_ConnHdlr vc_conn;
+	var hexstring imsi;
+	var OCT4 teid;
+	var PDU_UECUPS rx_uecups;
+	var UECUPS_CreateTun gtc;
+	var UECUPS_DestroyTun gtd;
+	var UECUPS_StartProgram sprog;
+
+	f_init(cfg);
+
+	while (true) {
+	alt {
+	/* route inbound GTP2-C based on IMSI or TEID */
+	[] GTP2C.receive(Gtp2cUnitdata:?) -> value g2c_ud {
+		var template hexstring imsi_t := f_gtp2c_extract_imsi(g2c_ud.gtpc);
+		if (not ispresent(g2c_ud.gtpc.tEID) or g2c_ud.gtpc.tEID == int2oct(0, 4)) {
+			TEID0.send(g2c_ud.gtpc) to vc_conn;
+		} else if (ispresent(g2c_ud.gtpc.tEID) and g2c_ud.gtpc.tEID != int2oct(0, 4)) {
+			vc_conn := f_comp_by_teid(g2c_ud.gtpc.tEID);
+			CLIENT.send(g2c_ud.gtpc) to vc_conn;
+		} else if (isvalue(imsi_t)) {
+			vc_conn := f_comp_by_imsi(valueof(imsi_t));
+			CLIENT.send(g2c_ud.gtpc) to vc_conn;
+		} else {
+			/* Send to all clients */
+			var integer i;
+			for (i := 0; i < sizeof(TidTable); i := i+1) {
+				if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) {
+					CLIENT.send(g2c_ud.gtpc) to TidTable[i].vc_conn;
+				}
+			}
+		}
+		}
+
+	[] TEID0.receive(PDU_GTPCv2:?) -> value g2c sender vc_conn {
+		/* patch in the next sequence number */
+		/* FIXME: do this only for outbound requests */
+		g2c.sequenceNumber := int2oct(g_c_seq_nr, 3);
+		g_c_seq_nr := g_c_seq_nr + 1;
+		/* build Gtp2cUnitdata */
+		g2c_ud := { peer := g_peer, gtpc := g2c };
+		GTP2C.send(g2c_ud);
+		}
+
+	[] CLIENT.receive(PDU_GTPCv2:?) -> value g2c sender vc_conn {
+		/* patch in the next sequence number */
+		/* FIXME: do this only for outbound requests */
+		g2c.sequenceNumber := int2oct(g_c_seq_nr, 3);
+		g_c_seq_nr := g_c_seq_nr + 1;
+		/* build Gtp2cUnitdata */
+		g2c_ud := { peer := g_peer, gtpc := g2c };
+		GTP2C.send(g2c_ud);
+		}
+
+	[] CLIENT_PROC.getcall(GTP2EM_register_imsi:{?}) -> param(imsi) sender vc_conn {
+		f_imsi_tbl_add(imsi, vc_conn);
+		CLIENT_PROC.reply(GTP2EM_register_imsi:{imsi}) to vc_conn;
+		}
+
+	[] CLIENT_PROC.getcall(GTP2EM_register_teid:{?}) -> param(teid) sender vc_conn {
+		f_tid_tbl_add(teid, vc_conn);
+		CLIENT_PROC.reply(GTP2EM_register_teid:{teid}) to vc_conn;
+		}
+	[] CLIENT_PROC.getcall(GTP2EM_allocate_teid:{}) -> sender vc_conn {
+		var OCT4 t := f_alloc_teid();
+		f_tid_tbl_add(t, vc_conn);
+		CLIENT_PROC.reply(GTP2EM_allocate_teid:{} value t) to vc_conn;
+		}
+	[] CLIENT_PROC.getcall(GTP2EM_create_tunnel:{?}) -> param(gtc) sender vc_conn {
+		rx_uecups := f_uecups_xceive({create_tun := gtc}, {create_tun_res:={result:=OK}});
+		CLIENT_PROC.reply(GTP2EM_create_tunnel:{gtc});
+		}
+	[] CLIENT_PROC.getcall(GTP2EM_destroy_tunnel:{?}) -> param(gtd) sender vc_conn {
+		rx_uecups := f_uecups_xceive({destroy_tun := gtd}, {destroy_tun_res:={result:=OK}});
+		CLIENT_PROC.reply(GTP2EM_destroy_tunnel:{gtd});
+		}
+	[] CLIENT_PROC.getcall(GTP2EM_start_program:{?}) -> param(sprog) sender vc_conn {
+		rx_uecups := f_uecups_xceive({start_program := sprog}, {start_program_res:=?});
+		/* if successful: store (pid, vc_conn) tuple so we can route program_term_ind */
+		if (rx_uecups.start_program_res.result == OK) {
+			f_pid_tbl_add(rx_uecups.start_program_res.pid, vc_conn);
+		}
+		CLIENT_PROC.reply(GTP2EM_start_program:{sprog} value rx_uecups.start_program_res);
+		}
+
+	}
+	}
+}
+
+
+/***********************************************************************
+ * Interaction between Main and Client Components
+ ***********************************************************************/
+type port GTP2EM_PT message {
+	inout PDU_GTPCv2, UECUPS_ProgramTermInd;
+} with { extension "internal" };
+
+signature GTP2EM_register_imsi(hexstring imsi);
+signature GTP2EM_register_teid(OCT4 teid);
+signature GTP2EM_allocate_teid() return OCT4;
+signature GTP2EM_create_tunnel(UECUPS_CreateTun gtc);
+signature GTP2EM_destroy_tunnel(UECUPS_DestroyTun gtd);
+signature GTP2EM_start_program(UECUPS_StartProgram sprog) return UECUPS_StartProgramRes;
+
+type port GTP2EM_PROC_PT procedure {
+	inout GTP2EM_register_imsi, GTP2EM_register_teid, GTP2EM_allocate_teid,
+	      GTP2EM_create_tunnel, GTP2EM_destroy_tunnel, GTP2EM_start_program;
+} with { extension "internal" };
+
+/***********************************************************************
+ * Client Component
+ ***********************************************************************/
+
+type component GTP2_ConnHdlr {
+	port GTP2EM_PT GTP2;
+	port GTP2EM_PROC_PT GTP2_PROC;
+};
+
+function f_gtp2_register_imsi(hexstring imsi) runs on GTP2_ConnHdlr {
+	GTP2_PROC.call(GTP2EM_register_imsi:{imsi}) {
+		[] GTP2_PROC.getreply(GTP2EM_register_imsi:{imsi});
+	}
+}
+
+function f_gtp2_register_teid(OCT4 teid) runs on GTP2_ConnHdlr {
+	GTP2_PROC.call(GTP2EM_register_teid:{teid}) {
+		[] GTP2_PROC.getreply(GTP2EM_register_teid:{teid});
+	}
+}
+
+function f_gtp2_allocate_teid() runs on GTP2_ConnHdlr return OCT4 {
+	var OCT4 t;
+	GTP2_PROC.call(GTP2EM_allocate_teid:{}) {
+		[] GTP2_PROC.getreply(GTP2EM_allocate_teid:{}) -> value t {
+			return t;
+		}
+	}
+}
+
+function f_gtp2_create_tunnel(template (value) UECUPS_CreateTun gtc)
+runs on GTP2_ConnHdlr {
+	GTP2_PROC.call(GTP2EM_create_tunnel:{valueof(gtc)}) {
+		[] GTP2_PROC.getreply(GTP2EM_create_tunnel:{gtc});
+	}
+}
+
+function f_gtp2_destroy_tunnel(template (value) UECUPS_DestroyTun gtd)
+runs on GTP2_ConnHdlr {
+	GTP2_PROC.call(GTP2EM_destroy_tunnel:{valueof(gtd)}) {
+		[] GTP2_PROC.getreply(GTP2EM_destroy_tunnel:{gtd});
+	}
+}
+
+function f_gtp2_start_program(template (value) UECUPS_StartProgram sprog)
+runs on GTP2_ConnHdlr return UECUPS_StartProgramRes {
+	var UECUPS_StartProgramRes res;
+	GTP2_PROC.call(GTP2EM_start_program:{valueof(sprog)}) {
+		[] GTP2_PROC.getreply(GTP2EM_start_program:{sprog}) -> value res;
+	}
+	return res;
+}
+
+
+
+}
diff --git a/library/GTPv2_Templates.ttcn b/library/GTPv2_Templates.ttcn
index 23b0053..af3b84b 100644
--- a/library/GTPv2_Templates.ttcn
+++ b/library/GTPv2_Templates.ttcn
@@ -30,6 +30,7 @@
 }
 
 template (present) PDU_GTPCv2 tr_PDU_GTP2C(template OCT4 teid := ?,
+					   template (present) OCT3 seq := ?,
 					   template (present) GTPCv2_PDUs pdus := ?,
 					   template PDU_GTPCv2 piggyback := omit) := {
 	spare := '000'B,
@@ -39,7 +40,7 @@
 	messageType := ?,
 	lengthf := ?,
 	tEID := teid,
-	sequenceNumber := ?,
+	sequenceNumber := seq,
 	spare3 := '00'O,
 	gtpcv2_pdu := pdus,
 	piggybackPDU_GTPCv2 := piggyback
@@ -62,6 +63,23 @@
 	iMSI_Value := imsi
 }
 
+template (present) MSISDN ts_GTP2C_msisdn(template (present) hexstring msisdn) := {
+	elementIdentifier := '4C'O,
+	lengthIndicator := 0, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	mSISDN_Value := msisdn
+}
+private function fs_GTP2C_msisdn(template (omit) hexstring msisdn) return
+template (omit) MSISDN {
+	if (istemplatekind(msisdn, "omit")) {
+		return omit;
+	} else {
+		return ts_GTP2C_msisdn(msisdn);
+	}
+}
+
+
 /* 8.4-1 */
 /*
 type enumerated GTP2C_Cause {
@@ -109,6 +127,25 @@
 	instanceOfOffendingIE := *,
 	spare3 := *
 }
+private function fs_GTP2C_Cause(template (omit) OCT1 cause, template (value) BIT1 cs) return
+template (omit) Cause {
+	if (istemplatekind(cause, "omit")) {
+		return omit;
+	} else {
+		return ts_GTP2C_Cause(cause, cs);
+	}
+}
+private function fr_GTP2C_Cause(template OCT1 cause) return
+template Cause {
+	if (istemplatekind(cause, "omit")) {
+		return omit;
+	} else if (istemplatekind(cause, "*")) {
+		return *;
+	} else {
+		return tr_GTP2C_Cause(cause);
+	}
+}
+
 
 /* 8.5 */
 template (value) AccessPointName ts_GTP2C_APN(template (value) octetstring apn) := {
@@ -126,6 +163,41 @@
 	aPN_Value := apn
 }
 
+/* 8.7 */
+template (value) AggregateMaximumBitRate
+ts_GTP2C_Ambr(integer ambr_ul, integer ambr_dl) := {
+	elementIdentifier := '48'O,
+	lengthIndicator := 0, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	aPN_AMBR_for_uplink := int2oct(ambr_ul, 4),
+	aPN_AMBR_for_downlink := int2oct(ambr_dl, 4)
+}
+
+/* 8.8 */
+template (value) EPS_BearerID
+ts_GTP2C_EpsBearerId(template (value) uint4_t bid) := {
+	elementIdentifier := '49'O,
+	lengthIndicator := 0, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	ePS_Bearer_ID_Value := bid,
+	spare2 := '0000'B,
+	additionalOctets := omit
+}
+template (present) EPS_BearerID
+tr_GTP2C_EpsBearerId(template (present) uint4_t bid) := {
+	elementIdentifier := '49'O,
+	lengthIndicator := ?, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	ePS_Bearer_ID_Value := bid,
+	spare2 := '0000'B,
+	additionalOctets := *
+}
+
+
+
 /* 8.14 */
 template (value) PDN_AddressAllocation
 ts_GTP2C_PdnAddrAlloc(template (value) BIT3 pdn_type,
@@ -156,6 +228,31 @@
 tr_GTP2C_PdnAddrAlloc_v4(template (present) OCT4 addr) :=
 	ts_GTP2C_PdnAddrAlloc('001'B, {iPv4_Address:=addr});
 
+/* 8.15 */
+template (value) Bearer_QoS
+ts_GTP2C_BearerQos(template (value) OCT1 qci,
+		   uint40_t max_br_ul, uint40_t max_br_dl,
+		   uint40_t g_br_ul, uint40_t g_br_dl,
+		   template (value) BIT4 prio_lvl := '1001'B,
+		   template (value) BIT1 pe_vuln := '0'B,
+		   template (value) BIT1 pe_capa := '0'B) := {
+	elementIdentifier := '50'O,
+	lengthIndicator := 0, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	pVI := pe_vuln,
+	spare2 := '0'B,
+	pL := prio_lvl,
+	pCI := pe_capa,
+	spare3 := '0'B,
+	labelQCI := qci,
+	maxBitrateUplink := int2oct(max_br_ul, 5),
+	maxBitrateDownLink := int2oct(max_br_dl, 5),
+	guaranteedBitrateUplink := int2oct(g_br_ul, 5),
+	guaranteedBitrateDownLink := int2oct(g_br_dl, 5),
+	additionalOctets := omit
+}
+
 /* 8.17 */
 template (value) RAT_Type ts_GTP2C_RatType(template (value) integer rat) := {
 	elementIdentifier := '53'O,
@@ -174,6 +271,66 @@
 	additionalOctets := *
 }
 
+/* 8.21 */
+function ts_GTP2C_UserLocInfo(template (omit) CGI cgi := omit,
+			      template (omit) SAI sai := omit,
+			      template (omit) RAI rai := omit,
+			      template (omit) TAI tai := omit,
+			      template (omit) ECGI ecgi := omit,
+			      template (omit) LAI lai := omit)
+return template (value) UserLocationInfo {
+	var template (value) UserLocationInfo uli;
+	uli.elementIdentifier := '56'O;
+	uli.lengthIndicator := 0; // overwritten
+	uli.instance := '0000'B;
+	uli.spare := '0000'B;
+	uli.spare2 := '00'B;
+	uli.additionalOctets := omit;
+
+	if (istemplatekind(cgi, "omit")) {
+		uli.cGI_Flag := '0'B;
+	} else {
+		uli.cGI_Flag := '1'B;
+	}
+	uli.cGI := cgi;
+
+	if (istemplatekind(sai, "omit")) {
+		uli.sAI_Flag := '0'B;
+	} else {
+		uli.sAI_Flag := '1'B;
+	}
+	uli.sAI := sai;
+
+	if (istemplatekind(rai, "omit")) {
+		uli.rAI_Flag := '0'B;
+	} else {
+		uli.rAI_Flag := '1'B;
+	}
+	uli.rAI := rai
+
+	if (istemplatekind(tai, "omit")) {
+		uli.tAI_Flag := '0'B;
+	} else {
+		uli.tAI_Flag := '1'B;
+	}
+	uli.tAI := tai
+
+	if (istemplatekind(ecgi, "omit")) {
+		uli.eCGI_Flag := '0'B;
+	} else {
+		uli.eCGI_Flag := '1'B;
+	}
+	uli.eCGI := ecgi;
+
+	if (istemplatekind(lai, "omit")) {
+		uli.lAI_Flag := '0'B;
+	} else {
+		uli.lAI_Flag := '1'B;
+	}
+	uli.lAI := lai
+
+	return uli;
+}
 
 /* 8.22 */
 private function f_bit4oct(template (omit) octetstring os) return BIT1
@@ -184,16 +341,59 @@
 		return '1'B;
 	}
 }
+type enumerated FteidInterface {
+	FTEID_IF_S1U_eNodeB_GTPU	(0),
+	FTEID_IF_S1U_SGW_GTPU		(1),
+	FTEID_IF_S12_RNC_GTPU		(2),
+	FTEID_IF_S12_SGW_GTPU		(3),
+	FTEID_IF_S5S8_SGW_GTPU		(4),
+	FTEID_IF_S5S8_PGW_GTPU		(5),
+	FTEID_IF_S5S8_SGW_GTPC		(6),
+	FTEID_IF_S5S8_PGW_GTPC		(7),
+	FTEID_IF_S5S8_SGW_PMIPv6	(8),
+	FTEID_IF_S5S8_PGW_PMIPv6	(9),
+	FTEID_IF_S11_MME_GTPC		(10),
+	FTEID_IF_S11S4_SGW_GTPC		(11),
+	FTEID_IF_S10ND26_MME_GTPC	(12),
+	FTEID_IF_S3_MME_GTPC		(13),
+	FTEID_IF_S3_SGSN_GTPC		(14),
+	FTEID_IF_S4_SGSN_GTPU		(15),
+	FTEID_IF_S4_SGW_GTPU		(16),
+	FTEID_IF_S16_SGSN_GTPC		(18),
+	FTEID_IF_eNB_GTPU_DL_DATA_FW	(19),
+	FTEID_IF_eNB_GTPU_UL_DATA_FW	(20),
+	FTEID_IF_RNC_GTPU_DATA_FW	(21),
+	FTEID_IF_SGSN_GTPU_DATA_FW	(22),
+	FTEID_IF_SGWUPF_GTPU_DL_DATA_FW	(23),
+	FTEID_IF_Sm_MMBS_GW_GTPC	(24),
+	FTEID_IF_Sn_MMBS_GW_GTPC	(25),
+	FTEID_IF_Sm_MME_GTPC		(26),
+	FTEID_IF_Sn_MME_GTPC		(27),
+	FTEID_IF_SGW_GTPU_UL_DATA_FW	(28),
+	FTEID_IF_Sn_SGSN_GTPU		(29),
+	FTEID_IF_S2b_ePDG_GTPC		(30),
+	FTEID_IF_S2bU_ePDG_GTPU		(31),
+	FTEID_IF_S2b_PGW_GTPC		(32),
+	FTEID_IF_S2bU_PGW_GTPU		(33),
+	FTEID_IF_S2a_TWAN_GTPU		(34),
+	FTEID_IF_S2a_TWAN_GTPC		(35),
+	FTEID_IF_S2a_PGW_GTPC		(36),
+	FTEID_IF_S2a_PGW_GTPU		(37),
+	FTEID_IF_S11_MME_GTPU		(38),
+	FTEID_IF_S11_SGW_GTPU		(39),
+	FTEID_IF_N26_AMF_GTPC		(40)
+};
 template (value) FullyQualifiedTEID
-ts_GTP2C_FTEID(integer if_type, OCT4 teid, template (omit) OCT4 v4_addr := omit,
+ts_GTP2C_FTEID(FteidInterface if_type, OCT4 teid, uint4_t instance := 0,
+		template (omit) OCT4 v4_addr := omit,
 		template (omit) OCT16 v6_addr := omit) := {
 	elementIdentifier := '57'O,
 	lengthIndicator := 0, /* overwritten */
-	instance := '0000'B,
+	instance := int2bit(instance, 4),
 	spare := '0000'B,
-	interfaceType := if_type,
-	v6_Flag := f_bit4oct(v4_addr),
-	v4_Flag := f_bit4oct(v6_addr),
+	interfaceType := enum2int(if_type),
+	v6_Flag := f_bit4oct(v6_addr),
+	v4_Flag := f_bit4oct(v4_addr),
 	tEID_GRE_Key := teid,
 	iPv4_Address := v4_addr,
 	iPv6_Address := v6_addr,
@@ -201,11 +401,12 @@
 }
 template (present) FullyQualifiedTEID
 tr_GTP2C_FTEID(template (present) integer if_type, template (present) OCT4 teid,
+		template BIT4 instance := ?,
 		template OCT4 v4_addr := omit,
 		template OCT16 v6_addr := omit) := {
 	elementIdentifier := '57'O,
 	lengthIndicator := ?,
-	instance := ?,
+	instance := instance,
 	spare := '0000'B,
 	interfaceType := if_type,
 	v6_Flag := ?,
@@ -216,6 +417,134 @@
 	additionalOctets := omit
 }
 
+/* 8.28 */
+template (value) BearerContextGrouped
+ts_GTP2C_BcGrouped(template (value) BearerContextIEs ies) := {
+	elementIdentifier := '5D'O,
+	lengthIndicator := 0, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	bearerContextIEs := ies
+}
+template (present) BearerContextGrouped
+tr_GTP2C_BcGrouped(template (present) BearerContextIEs ies) := {
+	elementIdentifier := '5D'O,
+	lengthIndicator := ?, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	bearerContextIEs := ies
+}
+
+
+
+/* 8.30 */
+template (value) ChargingCharacteristics
+ts_GTP2C_ChargingCaracteristics(template (value) OCT2 cc) := {
+	elementIdentifier := '5F'O,
+	lengthIndicator := 0, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	chargingCharacteristicsValue := cc,
+	additionalOctets := omit
+}
+template (present) ChargingCharacteristics
+tr_GTP2C_ChargingCaracteristics(template (present) OCT2 cc) := {
+	elementIdentifier := '5F'O,
+	lengthIndicator := ?, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	chargingCharacteristicsValue := cc,
+	additionalOctets := omit
+}
+
+
+/* 8.34 */
+template (value) PDN_Type
+ts_GTP2C_PdnType(template (value) BIT3 pdn_type) := {
+	elementIdentifier := '63'O,
+	lengthIndicator := 0,
+	instance := '0000'B,
+	spare := '0000'B,
+	pDN_TypeValue := pdn_type,
+	spare2 := '00000'B,
+	additionalOctets := omit
+}
+template (present) PDN_Type
+tr_GTP2C_PdnType(template (present) BIT3 pdn_type) := {
+	elementIdentifier := '63'O,
+	lengthIndicator := ?,
+	instance := ?,
+	spare := ?,
+	pDN_TypeValue := pdn_type,
+	spare2 := ?,
+	additionalOctets := *
+}
+
+/* 8.35 */
+template (value) ProcedureTransactionID
+ts_GTP2C_ProcTransId(template (value) integer pti) := {
+	elementIdentifier := '64'O,
+	lengthIndicator := 0,
+	instance := '0000'B,
+	spare := '0000'B,
+	pTI_Value := pti,
+	additionalOctets := omit
+}
+template (present) ProcedureTransactionID
+tr_GTP2C_ProcTransId(template (present) integer pti) := {
+	elementIdentifier := '64'O,
+	lengthIndicator := ?,
+	instance :=?,
+	spare := ?,
+	pTI_Value := pti,
+	additionalOctets := *
+}
+
+
+/* 8.57 */
+template (value) APN_Restriction
+ts_GTP2C_ApnRestriction(template (value) integer val) := {
+	elementIdentifier := '7F'O,
+	lengthIndicator := 0,
+	instance := '0000'B,
+	spare := '0000'B,
+	restrictionTypeValue := val,
+	additionalOctets := omit
+}
+template (present) APN_Restriction
+tr_GTP2C_ApnRestriction(template (present) integer val) := {
+	elementIdentifier := '7F'O,
+	lengthIndicator := ?,
+	instance := '0000'B,
+	spare := ?,
+	restrictionTypeValue := val,
+	additionalOctets := *
+}
+
+
+/* 8.58 */
+template (value) SelectionMode
+ts_GTP2C_SelectionMode(template (value) integer mode) := {
+	elementIdentifier := '80'O,
+	lengthIndicator := 0, /* overwritten */
+	instance := '0000'B,
+	spare := '0000'B,
+	selectionModeValue := mode,
+	spare2 := '000000'B,
+	additionalOctets := omit
+}
+template (present) SelectionMode
+tr_GTP2C_SelectionMode(template (present) integer mode) := {
+	elementIdentifier := '80'O,
+	lengthIndicator := ?,
+	instance := ?,
+	spare := ?,
+	selectionModeValue := mode,
+	spare2 := ?,
+	additionalOctets := *
+}
+
+
 
 
 template (value) PDU_GTPCv2 ts_PDU_GTP2C(template (omit) OCT4 teid, template (value) OCT3 seq,
@@ -236,8 +565,117 @@
 }
 
 
+template (value) PDU_GTPCv2
+ts_GTP2C_EchoReq(template (value) integer rec_val) :=
+ts_PDU_GTP2C(omit, '000000'O, '01'O, {
+	echoRequest := {
+		recovery := {
+			elementIdentifier := '03'O,
+			lengthIndicator := 0,
+			instance := '0000'B,
+			spare := '0000'B,
+			recoveryValue := rec_val
+		},
+		sendingNodeFeatures := omit,
+		privateExtension := omit
+	}});
 template (present) PDU_GTPCv2
-tr_GTP2C_CreateSessionReq(template (present) hexstring imsi) := tr_PDU_GTP2C('00000000'O, {
+tr_GTP2C_EchoReq(template (present) OCT3 seq := ?) :=
+tr_PDU_GTP2C(omit, seq, { echoRequest := ? }, omit);
+
+template (value) PDU_GTPCv2
+ts_GTP2C_EchoResp(template (value) integer rec_val) :=
+ts_PDU_GTP2C(omit, '000000'O, '02'O, {
+	echoRequest := {
+		recovery := {
+			elementIdentifier := '03'O,
+			lengthIndicator := 0,
+			instance := '0000'B,
+			spare := '0000'B,
+			recoveryValue := rec_val
+		},
+		sendingNodeFeatures := omit,
+		privateExtension := omit
+	}});
+template (present) PDU_GTPCv2
+tr_GTP2C_EchoResp(template (present) OCT3 seq := ?) :=
+tr_PDU_GTP2C(omit, seq, { echoResponse := ? }, omit);
+
+
+
+template (present) PDU_GTPCv2
+ts_GTP2C_CreateSessionReq(template (value) hexstring imsi, template (omit) hexstring msisdn,
+			  integer rat_type, template (value) FullyQualifiedTEID sender_fteid,
+			  template (value) octetstring apn, template (value) BIT3 pdn_type,
+			  template (omit) FullyQualifiedTEID_List teid_list,
+			  template (value) OCT2 chg_car, template (value) uint4_t bearer_id,
+			  template (value) Bearer_QoS qos := ts_GTP2C_BearerQos('09'O, 0,0,0,0)) :=
+ts_PDU_GTP2C('00000000'O, '000000'O, '20'O, {
+	createSessionRequest := {
+		iMSI := ts_GTP2C_Imsi(imsi),
+		mSISDN := fs_GTP2C_msisdn(msisdn),
+		mEI := omit,
+		userLocationInfo := omit,
+		servingNetwork := omit,
+		rAT_Type := ts_GTP2C_RatType(rat_type),
+		indication := omit,
+		fullyQualifiedTEID := { sender_fteid },
+		accessPointName := ts_GTP2C_APN(apn),
+		selectionMode := ts_GTP2C_SelectionMode(0),
+		pDN_Type := ts_GTP2C_PdnType(pdn_type),
+		pDN_AddressAllocation := ts_GTP2C_PdnAddrAlloc('001'B, {iPv4_Address:='00000000'O}),
+		maxAPN_Restriction := ts_GTP2C_ApnRestriction(0),
+		ambr := ts_GTP2C_Ambr(102400, 102400),
+		linkedEPS_Bearer_ID := omit,
+		trustedWLANModeIndication := omit,
+		protocolConfigOptions := omit,
+		bearerContextGrouped := {
+			ts_GTP2C_BcGrouped({
+				ePS_Bearer_ID := ts_GTP2C_EpsBearerId(bearer_id),
+				cause := omit,
+				ePS_Bearer_TFT := omit,
+				fullyQualifiedTEID := teid_list,
+				bearerLevel_QoS := qos,
+				chargingID := omit,
+				bearerFlags := omit,
+				transactionIdentifier := omit,
+				protocolConfigOptions := omit,
+				rAN_NASCause := omit,
+				additionalProtocolConfigOptions := omit,
+				extendedProtocolConfigOptions := omit
+				})
+		},
+		traceInformation := omit,
+		recovery := omit,
+		csid := omit,
+		uE_TimeZone := omit,
+		user_CSG_Information := omit,
+		chargingCharacteristics := ts_GTP2C_ChargingCaracteristics(chg_car),
+		lDN := omit,
+		signallingPriorityIndication := omit,
+		iP_Addr := omit,
+		portNumber := omit,
+		aPCO := omit,
+		trustedWLANAccessNetworkIdentifier := omit,
+		cNOperatorSelectionEntity := omit,
+		presenceReportingAreaInformation := omit,
+		overloadControlInformationGrouped := omit,
+		originationTimeStamp := omit,
+		maximumWaitTime := omit,
+		wLANLocationTimestamp := omit,
+		nBIFOMContainer := omit,
+		remoteUEContextGrouped := omit,
+		nodeIdentifier := omit,
+		extendedProtocolConfigOptions := omit,
+		servingPLMNRateControl := omit,
+		counter := omit,
+		privateExtension := omit
+	}});
+
+
+template (present) PDU_GTPCv2
+tr_GTP2C_CreateSessionReq(template (present) hexstring imsi) :=
+tr_PDU_GTP2C('00000000'O, ?, {
 	createSessionRequest := {
 		iMSI := tr_GTP2C_Imsi(imsi),
 		mSISDN := *,
@@ -287,7 +725,7 @@
 template (value) PDU_GTPCv2
 ts_GTP2C_CreateSessionResp(template (value) FullyQualifiedTEID_List fteids,
 			   template (value) PDN_AddressAllocation addr) :=
-ts_PDU_GTP2C('00000000'O, '000000'O, '20'O, {
+ts_PDU_GTP2C('00000000'O, '000000'O, '21'O, {
 	createSessionResponse := {
 		cause := ts_GTP2C_Cause(int2oct(16, 1), '0'B),
 		changeReportingAction := omit,
@@ -317,6 +755,219 @@
 		extendedProtocolConfigOptions := omit,
 		privateExtension := omit
 	}});
+template (present) PDU_GTPCv2
+tr_GTP2C_CreateSessionResp(template (present) OCT4 d_teid := ?,
+			   template (present) OCT3 seq := ?,
+			   template (present) OCT1 cause := ?,
+			   template FullyQualifiedTEID_List fteids := *,
+			   template PDN_AddressAllocation addr := *,
+			   template BearerContextGrouped_List bctxg := *) :=
+tr_PDU_GTP2C(d_teid, seq, {
+	createSessionResponse := {
+		cause := tr_GTP2C_Cause(cause),
+		changeReportingAction := *,
+		cSG_InformationReportingAction := *,
+		heNBInformationReporting := *,
+		fullyQualifiedTEID := fteids,
+		pDN_AddressAllocation := addr,
+		aPN_Restriction := ?,
+		ambr := *,
+		linkedEPS_Bearer_ID := *,
+		protocolConfigOptions := *,
+		bearerContextGrouped := bctxg,
+		recovery := *,
+		chargingGatewayName := *,
+		chargingGatewayAddress := *,
+		csid := *,
+		lDN := *,
+		pGW_Back_OffTime := *,
+		aPCO := *,
+		trustedWLANIPv4Parameters := *,
+		indicationFlags := *,
+		presenceReportingAreaAction := *,
+		loadControlInformationGrouped := *,
+		overloadControlInformationGrouped := *,
+		nBIFOMContainer := *,
+		pDNConnectionChargingID := *,
+		extendedProtocolConfigOptions := *,
+		privateExtension := *
+	}});
+
+
+template (value) PDU_GTPCv2
+ts_GTP2C_DeleteSessionReq(template (value) OCT4 d_teid,
+			  template (omit) OCT1 cause := omit,
+			  template (value) FullyQualifiedTEID sender_fteid,
+			  template (omit) FullyQualifiedTEID_List teid_list := omit,
+			  template (value) uint4_t bearer_id) :=
+ts_PDU_GTP2C(d_teid, '000000'O, '24'O, {
+	deleteSessionRequest := {
+		cause := fs_GTP2C_Cause(cause, '0'B),
+		linkedEPS_Bearer_ID := ts_GTP2C_EpsBearerId(bearer_id),
+		uLI := omit,
+		indicationFlags := omit,
+		protocolConfigOptions := omit,
+		originatingNode := omit,
+		fullyQualifiedTEID := sender_fteid,
+		uE_TimeZone := omit,
+		uLITimestamp := omit,
+		rANNASReleaseCause := omit,
+		trustedWLANAccessNetworkIdentifier := omit,
+		tWANIdentifierTimestamp := omit,
+		overloadControlInformationGrouped := omit,
+		uELocalIP_Addr := omit,
+		portNumber := omit,
+		extendedProtocolConfigOptions := omit,
+		privateExtension := omit
+	}});
+template (present) PDU_GTPCv2
+tr_GTP2C_DeleteSessionReq(template (present) OCT4 d_teid,
+			  template (present) OCT3 seq := ?,
+			  template (omit) OCT1 cause,
+			  template (present) FullyQualifiedTEID sender_fteid,
+			  template FullyQualifiedTEID_List teid_list,
+			  template (present) uint4_t bearer_id) :=
+tr_PDU_GTP2C(d_teid, seq, {
+	deleteSessionRequest := {
+		cause := fr_GTP2C_Cause(cause),
+		linkedEPS_Bearer_ID := tr_GTP2C_EpsBearerId(bearer_id),
+		uLI := *,
+		indicationFlags := *,
+		protocolConfigOptions := *,
+		originatingNode := *,
+		fullyQualifiedTEID := sender_fteid,
+		uE_TimeZone := *,
+		uLITimestamp := *,
+		rANNASReleaseCause := *,
+		trustedWLANAccessNetworkIdentifier := *,
+		tWANIdentifierTimestamp := *,
+		overloadControlInformationGrouped := *,
+		uELocalIP_Addr := *,
+		portNumber := *,
+		extendedProtocolConfigOptions := *,
+		privateExtension := *
+	}});
+
+
+template (value) PDU_GTPCv2
+ts_GTP2C_DeleteSessionResp(template (value) OCT4 d_teid,
+			   template (value) OCT3 seq,
+			   template (value) OCT1 cause) :=
+ts_PDU_GTP2C(d_teid, '000000'O, '25'O, {
+	deleteSessionResponse := {
+		cause := ts_GTP2C_Cause(cause, '0'B),
+		recovery := omit,
+		protocolConfigOptions := omit,
+		indicationFlags := omit,
+		loadControlInformationGrouped := omit,
+		overloadControlInformationGrouped := omit,
+		extendedProtocolConfigOptions := omit,
+		privateExtension := omit
+
+	}});
+template (present) PDU_GTPCv2
+tr_GTP2C_DeleteSessionResp(template (present) OCT4 d_teid,
+			   template (present) OCT3 seq := ?,
+			   template (present) OCT1 cause := ?
+			) :=
+tr_PDU_GTP2C(d_teid, seq, {
+	deleteSessionResponse := {
+		cause := tr_GTP2C_Cause(cause),
+		recovery := *,
+		protocolConfigOptions := *,
+		indicationFlags := *,
+		loadControlInformationGrouped := *,
+		overloadControlInformationGrouped := *,
+		extendedProtocolConfigOptions := *,
+		privateExtension := *
+	}});
+
+template (value) PDU_GTPCv2
+ts_GTP2C_CreateBearerReq(template (value) OCT4 d_teid,
+			 template (value) integer proc_trans_id,
+			 template (value) uint4_t linked_id,
+			 template (value) uint4_t bearer_id,
+			 template (omit) FullyQualifiedTEID_List teid_list,
+			 template (value) Bearer_QoS qos := ts_GTP2C_BearerQos('09'O, 0,0,0,0)) :=
+ts_PDU_GTP2C(d_teid, '000000'O, '5F'O, {
+	createBearerRequest := {
+		procedureTransactionID := ts_GTP2C_ProcTransId(proc_trans_id),
+		linkedEPS_BearerID := ts_GTP2C_EpsBearerId(linked_id),
+		protocolConfigOptions := omit,
+		bearerContextGrouped := {
+			ts_GTP2C_BcGrouped({
+				ePS_Bearer_ID := ts_GTP2C_EpsBearerId(bearer_id),
+				cause := omit,
+				ePS_Bearer_TFT := omit,
+				fullyQualifiedTEID := teid_list,
+				bearerLevel_QoS := qos,
+				chargingID := omit,
+				bearerFlags := omit,
+				transactionIdentifier := omit,
+				protocolConfigOptions := omit,
+				rAN_NASCause := omit,
+				additionalProtocolConfigOptions := omit,
+				extendedProtocolConfigOptions := omit
+				})
+		},
+		csid := omit,
+		changeReportingAction := omit,
+		cSG_InformationReportingAction := omit,
+		heNBInformationReporting := omit,
+		presenceReportingAreaAction := omit,
+		indicationFlags := omit,
+		loadControlInformationGrouped := omit,
+		overloadControlInformationGrouped := omit,
+		nBIFOMContainer := omit,
+		privateExtension := omit
+	}});
+
+
+template (value) PDU_GTPCv2
+ts_GTP2C_DeleteBearerReq(template (value) OCT4 d_teid,
+			 template (value) integer proc_trans_id,
+			 template (value) uint4_t bearer_id,
+			 template (value) OCT1 cause) :=
+ts_PDU_GTP2C(d_teid, '000000'O, '63'O, {
+	deleteBearerRequest := {
+		epsBearerIdentity := { ts_GTP2C_EpsBearerId(bearer_id) },
+		bearerContextGrouped := omit,
+		procedureTransactionID := ts_GTP2C_ProcTransId(proc_trans_id),
+		protocolConfigOptions := omit,
+		csid := omit,
+		cause := ts_GTP2C_Cause(cause, '0'B),
+		indicationFlags := omit,
+		loadControlInformationGrouped := omit,
+		overloadControlInformationGrouped := omit,
+		nBIFOMContainer := omit,
+		extendedProtocolConfigOptions := omit,
+		privateExtension := omit
+	}});
+
+
+template (present) PDU_GTPCv2
+tr_GTP2C_DeleteBearerResp(template (present) OCT4 d_teid,
+			  template (present) OCT3 seq := ?,
+			  template (present) OCT1 cause := ?) :=
+tr_PDU_GTP2C(d_teid, seq, {
+	deleteBearerResponse := {
+		cause := tr_GTP2C_Cause(cause),
+		linkedBearerIdentity := *,
+		bearerContextGrouped := *,
+		recovery := *,
+		csid := *,
+		protocolConfigOptions := *,
+		uE_TimeZone := *,
+		uLI := *,
+		uLITimestamp := *,
+		trustedWLANAccessNetworkIdentifier := *,
+		tWANIdentifierTimestamp := *,
+		overloadControlInformationGrouped := *,
+		iP_Addr := *,
+		portNumber := *,
+		nBIFOMContainer := *,
+		privateExtension := *
+	}});
 
 
 
diff --git a/library/General_Types.ttcn b/library/General_Types.ttcn
index da396b7..40f0770 100644
--- a/library/General_Types.ttcn
+++ b/library/General_Types.ttcn
@@ -147,6 +147,7 @@
   type octetstring OCT3_14n length(3..14) with { variant "" };
   type octetstring OCT3_17n length(3..17) with { variant "" };
   type octetstring OCT4_8n length(4..8) with { variant "" };
+  type octetstring OCT4_16n length(4..16) with { variant "" };
 
 
   //****************************************************
diff --git a/library/Osmocom_Types.ttcn b/library/Osmocom_Types.ttcn
index 2e71123..3b2ca17 100644
--- a/library/Osmocom_Types.ttcn
+++ b/library/Osmocom_Types.ttcn
@@ -34,6 +34,7 @@
 	type integer uint13_t (0..8191) with { variant "unsigned 13 bit" };
 	type integer uint14_t (0..16383) with { variant "unsigned 14 bit" };
 	type integer uint15_t (0..32767) with { variant "unsigned 15 bit" };
+	type integer uint40_t (0..1099511627776) with { variant "unsigned 40 bit" };
 
 
 	const uint16_t c_UINT16_MAX := 65535;

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/17867
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: If73aa453e44ebf28032c60d207feb03e8061dc0c
Gerrit-Change-Number: 17867
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200419/4a640ee5/attachment.htm>


More information about the gerrit-log mailing list