Change in osmo-ttcn3-hacks[master]: Initial test suite for osmo-pcap-client

laforge gerrit-no-reply at lists.osmocom.org
Sat Apr 24 09:41:27 UTC 2021


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


Change subject: Initial test suite for osmo-pcap-client
......................................................................

Initial test suite for osmo-pcap-client

Change-Id: If4a1072e75cb64f785d660e4c828c0f521d84b16
---
M Makefile
A library/OPCAP_Adapter.ttcn
A library/OPCAP_CodecPort.ttcn
A library/OPCAP_CodecPort_CtrlFunct.ttcn
A library/OPCAP_CodecPort_CtrlFunctdef.cc
A library/OPCAP_Templates.ttcn
A library/OPCAP_Types.ttcn
A pcap-client/OPCAP_CLIENT_Tests.cfg
A pcap-client/OPCAP_CLIENT_Tests.default
A pcap-client/OPCAP_CLIENT_Tests.ttcn
A pcap-client/gen_links.sh
A pcap-client/osmo-pcap-client.cfg
12 files changed, 714 insertions(+), 0 deletions(-)



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

diff --git a/Makefile b/Makefile
index 81540ba..0567081 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,7 @@
 	mme \
 	msc \
 	ns \
+	pcap-client \
 	pcu \
 	pgw \
 	remsim \
diff --git a/library/OPCAP_Adapter.ttcn b/library/OPCAP_Adapter.ttcn
new file mode 100644
index 0000000..8bcc3fd
--- /dev/null
+++ b/library/OPCAP_Adapter.ttcn
@@ -0,0 +1,105 @@
+module OPCAP_Adapter {
+
+/* OPCAP Adapter layer, sitting on top of OPCAP_CodecPort.
+ * test suites can 'inherit' in order to have a OPCAP connection to the IUT which they're testing
+ *
+ * (C) 2021 by 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.
+ */
+
+
+import from Osmocom_Types all;
+import from General_Types all;
+import from OPCAP_Types all;
+import from OPCAP_Templates all;
+import from OPCAP_CodecPort all;
+import from OPCAP_CodecPort_CtrlFunct all;
+import from IPL4asp_Types all;
+import from IPL4asp_PortType all;
+import from Socket_API_Definitions all;
+
+const integer NUM_OPCAP := 3;
+
+type component OPCAP_Adapter_CT {
+	/* down-facing port to OPCAP Codec port */
+	port OPCAP_CODEC_PT OPCAP[NUM_OPCAP];
+	var IPL4asp_Types.ConnectionId g_opcap_conn_id[NUM_OPCAP] := { -1, -1, -1 };
+}
+
+private function f_set_tcp_segmentation(integer idx) runs on OPCAP_Adapter_CT {
+	/* Set function for dissecting the binary stream into packets */
+	var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
+	/* Offset: 2, size of length: 2, delta: 4, multiplier: 1, big-endian */
+	OPCAP_CodecPort_CtrlFunct.f_IPL4_setGetMsgLen(OPCAP[idx], g_opcap_conn_id[idx], vl_f, {2, 2, 4, 1, 0});
+}
+
+function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
+		   charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
+runs on OPCAP_Adapter_CT {
+	var IPL4asp_Types.Result res;
+	map(self:OPCAP[idx], system:OPCAP);
+	if (g_opcap_conn_id[idx] != -1) {
+		OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
+		g_opcap_conn_id[idx] := -1;
+	}
+	res := OPCAP_CodecPort_CtrlFunct.f_IPL4_connect(OPCAP[idx], remote_host, remote_port,
+							local_host, local_port, 0, { tcp :={} });
+	if (not ispresent(res.connId)) {
+		setverdict(fail, "Could not connect to OPCAP port, check your configuration ",
+			"{remote ", remote_host, ":", remote_port, " local ", local_host, ":", local_port, "}");
+		mtc.stop;
+	}
+	g_opcap_conn_id[idx] := res.connId;
+
+	f_set_tcp_segmentation(idx);
+}
+
+/* Function to use to bind to a local port as IPA server, accepting remote clients */
+function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
+runs on OPCAP_Adapter_CT {
+	var IPL4asp_Types.Result res;
+	map(self:OPCAP[idx], system:OPCAP);
+	if (g_opcap_conn_id[idx] != -1) {
+		OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
+		g_opcap_conn_id[idx] := -1;
+	}
+	res := OPCAP_CodecPort_CtrlFunct.f_IPL4_listen(OPCAP[idx], local_host, local_port, { tcp:={} });
+	if (not ispresent(res.connId)) {
+		setverdict(fail, "Could not bind to OPCAP port, check your configuration ",
+			   "{local ", local_host, ":", local_port, "}");
+		mtc.stop;
+	}
+	g_opcap_conn_id[idx] := res.connId;
+
+	f_set_tcp_segmentation(idx);
+}
+
+function f_wait_client_connect(integer idx) runs on OPCAP_Adapter_CT {
+	var IPL4asp_Types.PortEvent rx_event;
+	OPCAP[idx].receive(IPL4asp_Types.PortEvent:{connOpened:=?}) -> value rx_event {
+		log("Connection from ", rx_event.connOpened.remName, ":", rx_event.connOpened.remPort);
+		/* we want to store the client's connId, not the 'bind socket' one */
+		g_opcap_conn_id[idx] := rx_event.connOpened.connId;
+	}
+}
+
+function f_disconnect(integer idx) runs on OPCAP_Adapter_CT {
+	OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
+	OPCAP[idx].clear;
+};
+
+function f_opcap_send(template (value) OPCAP_PDU pdu, integer idx := 0) runs on OPCAP_Adapter_CT {
+	OPCAP[idx].send(ts_OPCAP_Send(g_opcap_conn_id[idx], pdu));
+}
+
+function f_opcap_exp(template OPCAP_PDU exp, integer idx := 0) runs on OPCAP_Adapter_CT return OPCAP_PDU {
+	var OPCAP_RecvFrom rf;
+	OPCAP[idx].receive(tr_OPCAP_Recv(g_opcap_conn_id[idx], exp)) -> value rf;
+	return rf.msg;
+}
+
+
+}
diff --git a/library/OPCAP_CodecPort.ttcn b/library/OPCAP_CodecPort.ttcn
new file mode 100644
index 0000000..f2d215d
--- /dev/null
+++ b/library/OPCAP_CodecPort.ttcn
@@ -0,0 +1,64 @@
+module OPCAP_CodecPort {
+
+/* Simple OPCAP Codec Port, translating between raw TCP octetstring payload
+ * towards the IPL4asp port provider, and OPCAP primitives
+ * which carry the decoded OPCAP data types as payload.
+ *
+ * (C) 2021 by 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.
+ */
+
+
+import from IPL4asp_PortType all;
+import from IPL4asp_Types all;
+import from OPCAP_Types all;
+
+type record OPCAP_RecvFrom {
+	ConnectionId	connId,
+	OPCAP_PDU	msg
+}
+
+type record OPCAP_Send {
+	ConnectionId	connId,
+	OPCAP_PDU	msg
+}
+
+template (value) OPCAP_Send ts_OPCAP_Send(ConnectionId conn_id, template (value) OPCAP_PDU msg) := {
+	connId := conn_id,
+	msg := msg
+}
+
+template OPCAP_RecvFrom tr_OPCAP_Recv(template ConnectionId conn_id, template OPCAP_PDU msg) := {
+	connId := conn_id,
+	msg := msg
+}
+
+private function IPL4_to_OPCAP_RecvFrom(in ASP_RecvFrom pin, out OPCAP_RecvFrom pout) {
+	pout.connId := pin.connId;
+	pout.msg := dec_OPCAP_PDU(pin.msg);
+} with { extension "prototype(fast)" }
+
+private function OPCAP_to_IPL4_Send(in OPCAP_Send pin, out ASP_Send pout) {
+	pout.connId := pin.connId;
+	pout.proto := { tcp := {} };
+	pout.msg := enc_OPCAP_PDU(pin.msg);
+} with { extension "prototype(fast)" }
+
+type port OPCAP_CODEC_PT message {
+	out	OPCAP_Send;
+	in	OPCAP_RecvFrom,
+		ASP_ConnId_ReadyToRelease,
+		ASP_Event;
+} with { extension "user IPL4asp_PT
+	out(OPCAP_Send -> ASP_Send: function(OPCAP_to_IPL4_Send))
+	in(ASP_RecvFrom -> OPCAP_RecvFrom: function(IPL4_to_OPCAP_RecvFrom);
+	   ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+	   ASP_Event -> ASP_Event: simple)"
+}
+
+
+
+}
diff --git a/library/OPCAP_CodecPort_CtrlFunct.ttcn b/library/OPCAP_CodecPort_CtrlFunct.ttcn
new file mode 100644
index 0000000..99a5fe7
--- /dev/null
+++ b/library/OPCAP_CodecPort_CtrlFunct.ttcn
@@ -0,0 +1,52 @@
+module OPCAP_CodecPort_CtrlFunct {
+
+  import from OPCAP_CodecPort all;
+  import from IPL4asp_Types all;
+
+  external function f_IPL4_listen(
+    inout OPCAP_CODEC_PT portRef,
+    in HostName locName,
+    in PortNumber locPort,
+    in ProtoTuple proto,
+    in OptionList options := {}
+  ) return Result;
+
+  external function f_IPL4_connect(
+    inout OPCAP_CODEC_PT portRef,
+    in HostName remName,
+    in PortNumber remPort,
+    in HostName locName,
+    in PortNumber locPort,
+    in ConnectionId connId,
+    in ProtoTuple proto,
+    in OptionList options := {}
+  ) return Result;
+
+  external function f_IPL4_close(
+    inout OPCAP_CODEC_PT portRef,
+    in ConnectionId id,
+    in ProtoTuple proto := { unspecified := {} }
+  ) return Result;
+
+  external function f_IPL4_setUserData(
+    inout OPCAP_CODEC_PT portRef,
+    in ConnectionId id,
+    in UserData userData
+  ) return Result;
+
+  external function f_IPL4_getUserData(
+    inout OPCAP_CODEC_PT portRef,
+    in ConnectionId id,
+    out UserData userData
+  ) return Result;
+
+  external function f_IPL4_setGetMsgLen(
+    inout OPCAP_CODEC_PT portRef,
+    in ConnectionId id,
+    inout f_IPL4_getMsgLen f,
+    in ro_integer msgLenArgs
+  );
+
+
+}
+
diff --git a/library/OPCAP_CodecPort_CtrlFunctdef.cc b/library/OPCAP_CodecPort_CtrlFunctdef.cc
new file mode 100644
index 0000000..b19138a
--- /dev/null
+++ b/library/OPCAP_CodecPort_CtrlFunctdef.cc
@@ -0,0 +1,66 @@
+#include "IPL4asp_PortType.hh"
+#include "OPCAP_CodecPort.hh"
+#include "IPL4asp_PT.hh"
+
+namespace OPCAP__CodecPort__CtrlFunct {
+
+  IPL4asp__Types::Result f__IPL4__listen(
+    OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
+    const IPL4asp__Types::HostName& locName,
+    const IPL4asp__Types::PortNumber& locPort,
+    const IPL4asp__Types::ProtoTuple& proto,
+    const IPL4asp__Types::OptionList& options)
+  {
+    return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+  }
+  
+  IPL4asp__Types::Result f__IPL4__connect(
+    OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
+    const IPL4asp__Types::HostName& remName,
+    const IPL4asp__Types::PortNumber& remPort,
+    const IPL4asp__Types::HostName& locName,
+    const IPL4asp__Types::PortNumber& locPort,
+    const IPL4asp__Types::ConnectionId& connId,
+    const IPL4asp__Types::ProtoTuple& proto,
+    const IPL4asp__Types::OptionList& options)
+  {
+    return f__IPL4__PROVIDER__connect(portRef, remName, remPort,
+                                      locName, locPort, connId, proto, options);
+  }
+
+  IPL4asp__Types::Result f__IPL4__close(
+    OPCAP__CodecPort::OPCAP__CODEC__PT& portRef, 
+    const IPL4asp__Types::ConnectionId& connId, 
+    const IPL4asp__Types::ProtoTuple& proto)
+  {
+      return f__IPL4__PROVIDER__close(portRef, connId, proto);
+  }
+
+  IPL4asp__Types::Result f__IPL4__setUserData(
+    OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
+    const IPL4asp__Types::ConnectionId& connId,
+    const IPL4asp__Types::UserData& userData)
+  {
+    return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
+  }
+  
+  IPL4asp__Types::Result f__IPL4__getUserData(
+    OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
+    const IPL4asp__Types::ConnectionId& connId,
+    IPL4asp__Types::UserData& userData)
+  {
+    return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
+  }
+
+  void f__IPL4__setGetMsgLen(
+    OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
+    const IPL4asp__Types::ConnectionId& connId,
+    Socket__API__Definitions::f__getMsgLen& f,
+    const Socket__API__Definitions::ro__integer& msgLenArgs)
+  {
+    return f__IPL4__PROVIDER__setGetMsgLen(portRef, connId, f, msgLenArgs);
+  }
+
+
+}
+
diff --git a/library/OPCAP_Templates.ttcn b/library/OPCAP_Templates.ttcn
new file mode 100644
index 0000000..0a1c884
--- /dev/null
+++ b/library/OPCAP_Templates.ttcn
@@ -0,0 +1,54 @@
+module OPCAP_Templates {
+
+/* OPCAP_Templates, defining TTCN-3 templates for the osmo-pcap protocol.
+ *
+ * OPCAP is a non-standard protocol used between osmo-pcap-client and osmo-pcap-server.
+ *
+ * (C) 2021 by 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.
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from OPCAP_Types all;
+
+
+template (present) OPCAP_PDU tr_OPCAP_FILE_HDR(template (present) uint32_t linktype := ?) := {
+	msg_type := PKT_LINK_HDR,
+	spare := ?,
+	len := 24,
+	u := {
+		file := {
+			magic := PCAP_MAGIC,
+			version_major := PCAP_VERSION_MAJOR,
+			version_minor := PCAP_VERSION_MINOR,
+			thiszone := 0,
+			sigfigs := 0,
+			snaplen := 9000,
+			linktype := linktype
+		}
+	}
+}
+
+template (present) OPCAP_PDU tr_OPCAP_PKT(template (present) octetstring payload,
+					  template (present) uint32_t caplen := ?,
+					  template (present) uint32_t len := ?) := {
+	msg_type := PKT_LINK_DATA,
+	spare := ?,
+	len := ?,
+	u := {
+		packet := {
+			ts_sec := ?,
+			ts_usec := ?,
+			caplen := caplen,
+			len := len,
+			payload := payload
+		}
+	}
+}
+
+
+};
diff --git a/library/OPCAP_Types.ttcn b/library/OPCAP_Types.ttcn
new file mode 100644
index 0000000..d244fef
--- /dev/null
+++ b/library/OPCAP_Types.ttcn
@@ -0,0 +1,78 @@
+module OPCAP_Types {
+
+/* OPCAP_Types, defining abstract TTCN-3 data types for the osmo-pcap protocol.
+ *
+ * OPCAP is a non-standard protocol used between osmo-pcap-client and osmo-pcap-server.
+ *
+ * (C) 2021 by 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.
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+type enumerated OpcapMsgType {
+	PKT_LINK_HDR	(0),
+	PKT_LINK_DATA	(1)
+} with { variant "FIELDLENGTH(8)" };
+
+type record OPCAP_PDU {
+	OpcapMsgType msg_type,
+	uint8_t spare,
+	uint16_t len,
+	OpcapBodyUnion u
+} with {
+	variant (len) "LENGTHTO(u)"
+	variant (len) "BYTEORDER(last)"
+	variant (u) "CROSSTAG(
+		file,	msg_type = PKT_LINK_HDR;
+		packet,	msg_type = PKT_LINK_DATA;
+			)"
+};
+
+type union OpcapBodyUnion {
+	PcapFileHeader file,
+	OpcapPacket packet
+};
+
+/* header in front of a PKT_LINK_DATA */
+type record OpcapPacket {
+	uint32_t ts_sec,
+	uint32_t ts_usec,
+	uint32_t caplen,
+	uint32_t len,
+	octetstring payload
+} with {
+	variant (caplen) "LENGTHTO(payload)"
+};
+
+/* below definitions are from pcap/pcap.h */
+const uint16_t PCAP_VERSION_MAJOR := 2;
+const uint16_t PCAP_VERSION_MINOR := 4;
+const uint32_t PCAP_MAGIC := 2712847316; //0xA1B2C3D4;
+
+type record PcapFileHeader {
+	uint32_t magic,
+	uint16_t version_major,
+	uint16_t version_minor,
+	uint32_t thiszone,
+	uint32_t sigfigs,
+	uint32_t snaplen,
+	uint32_t linktype
+};
+
+/* below definitions are from pcap/dlt.h */
+const uint32_t DLT_LINUX_SLL := 113;
+const uint32_t DLT_EN10MB := 1;
+
+
+external function enc_OPCAP_PDU(in OPCAP_PDU msg) return octetstring
+	with { extension "prototype(convert) encode(RAW)" };
+
+external function dec_OPCAP_PDU(in octetstring msg) return OPCAP_PDU
+	with { extension "prototype(convert) decode(RAW)" };
+
+} with { encode "RAW"; variant "FIELDORDER(msb)"; variant "BYTEORDER(first)" };
diff --git a/pcap-client/OPCAP_CLIENT_Tests.cfg b/pcap-client/OPCAP_CLIENT_Tests.cfg
new file mode 100644
index 0000000..3476c2f
--- /dev/null
+++ b/pcap-client/OPCAP_CLIENT_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./OPCAP_CLIENT_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+OPCAP_CLIENT_Tests.control
diff --git a/pcap-client/OPCAP_CLIENT_Tests.default b/pcap-client/OPCAP_CLIENT_Tests.default
new file mode 100644
index 0000000..2b1677b
--- /dev/null
+++ b/pcap-client/OPCAP_CLIENT_Tests.default
@@ -0,0 +1,19 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.VTY.CTRL_MODE := "client"
+*.VTY.CTRL_HOSTNAME := "127.0.0.1"
+*.VTY.CTRL_PORTNUM := "4237"
+*.VTY.CTRL_LOGIN_SKIPPED := "yes"
+*.VTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.VTY.CTRL_READMODE := "buffered"
+*.VTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.VTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.VTY.PROMPT1 := "OsmoPCAPClient> "
+*.TCP.noDelay := "yes" // turn off nagle
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoPCAPClient"
+
+[EXECUTE]
diff --git a/pcap-client/OPCAP_CLIENT_Tests.ttcn b/pcap-client/OPCAP_CLIENT_Tests.ttcn
new file mode 100644
index 0000000..5f59caf
--- /dev/null
+++ b/pcap-client/OPCAP_CLIENT_Tests.ttcn
@@ -0,0 +1,212 @@
+module OPCAP_CLIENT_Tests {
+
+import from OPCAP_Adapter all;
+import from OPCAP_Types all;
+import from OPCAP_Templates all;
+
+import from IPL4asp_Types all;
+import from IPL4asp_PortType all;
+import from Osmocom_Types all;
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+import from Socket_API_Definitions all;
+
+type record IpPort {
+	charstring ip,
+	integer udp_port
+};
+
+modulepar {
+	/* local IP address listening for OPCAP connections */
+	charstring mp_local_opcap_ip := "127.0.0.1";
+	/* local TCP base port for inbound OPCAP connections */
+	integer mp_local_opcap_port := 5000;
+
+	/* IP + port for simulating user traffic */
+	IpPort mp_traffic_a := { "127.0.0.23", 44423 };
+	IpPort mp_traffic_b := { "127.0.0.42", 44442 };
+};
+
+type component test_CT extends OPCAP_Adapter_CT {
+	timer g_Tguard := 30.0;
+
+	port TELNETasp_PT VTY;
+
+	/* port to generate IP traffic that may or may not be captured */
+	port IPL4asp_PT IP;
+	var integer g_traffic_conn_id[2];
+};
+
+private altstep as_Tguard() runs on test_CT {
+[] g_Tguard.timeout {
+	setverdict(fail, "global guard timeout");
+	mtc.stop;
+	}
+}
+
+/* initialize one of the OPCAP servers, wait for client to connect */
+private function f_init_one_srv(integer idx, template (present) uint32_t linktype) runs on test_CT {
+	/* start guard timer */
+	activate(as_Tguard());
+	g_Tguard.start;
+	log("Waiting for client-", idx, " connection...");
+	/* wait for connection */
+	f_bind(mp_local_opcap_ip, mp_local_opcap_port+idx, idx);
+	f_wait_client_connect(idx);
+	/* wait for file header */
+	f_opcap_exp(tr_OPCAP_FILE_HDR(linktype), idx);
+};
+
+
+/* global initialization */
+private function f_init() runs on test_CT {
+	map(self:VTY, system:VTY);
+	f_vty_set_prompts(VTY);
+	f_vty_transceive(VTY, "enable");
+
+	map(self:IP, system:IP);
+	var IPL4asp_Types.Result res
+
+	/* 0 -> 1 */
+	res := f_IPL4_connect(IP, mp_traffic_b.ip, mp_traffic_b.udp_port,
+			      mp_traffic_a.ip, mp_traffic_a.udp_port, -1, { udp:={} });
+	g_traffic_conn_id[0] := res.connId;
+
+	/* 1 -> 0 */
+	res := f_IPL4_connect(IP, mp_traffic_a.ip, mp_traffic_a.udp_port,
+			      mp_traffic_b.ip, mp_traffic_b.udp_port, -1, { udp:={} });
+	g_traffic_conn_id[1] := res.connId;
+}
+
+/* generate user traffic from A -> B */
+function f_trafic_pkt_ab(octetstring payload) runs on test_CT {
+	IP.send(ASP_Send:{g_traffic_conn_id[0], omit, payload})
+	IP.receive(ASP_RecvFrom:{g_traffic_conn_id[1], ?, ?, ?, ?, { udp:={} }, ?, payload});
+}
+
+/* generate user traffic from B -> A */
+function f_trafic_pkt_ba(octetstring payload) runs on test_CT {
+	IP.send(ASP_Send:{g_traffic_conn_id[1], omit, payload})
+	IP.receive(ASP_RecvFrom:{g_traffic_conn_id[0], ?, ?, ?, ?, { udp:={} }, ?, payload});
+}
+
+/* expect a specified UDP payload on the OPCAP connection 'idx' */
+function f_opcap_exp_udp(octetstring udp_payload, integer idx) runs on test_CT {
+	var octetstring rx_tail;
+	var integer udp_payload_len, rx_pdu_len;
+	var OPCAP_PDU rx_pdu;
+
+	udp_payload_len := lengthof(udp_payload);
+
+	/* sadly I couldn't figure out how to create an octetstring template
+	 * for 'match an octetstring ending in 'udp_payload' */
+	rx_pdu := f_opcap_exp(tr_OPCAP_PKT(?), idx);
+	rx_pdu_len := lengthof(rx_pdu.u.packet.payload);
+	rx_tail := substr(rx_pdu.u.packet.payload, rx_pdu_len - udp_payload_len, udp_payload_len);
+	if (rx_tail != udp_payload) {
+		log("captured UDP payload: ", rx_tail, " but expected: ", udp_payload);
+		setverdict(fail);
+	} else {
+		setverdict(pass);
+	}
+}
+
+/* create an additional pcap-store-connection via the VTY */
+function f_vty_create_addl_connection(integer idx) runs on test_CT
+{
+	f_vty_config3(VTY, { "client", "pcap-store-connectio second-" & int2str(idx) },
+			{ "server ip " & mp_local_opcap_ip,
+			  "server port " & int2str(mp_local_opcap_port + idx),
+			  "connect" }
+			);
+}
+
+
+
+/* wait for inbound client connection and reception of link header */
+testcase TC_connect_rx_hdr() runs on test_CT
+{
+	f_init();
+	f_init_one_srv(0, ?);
+	setverdict(pass);
+}
+
+/* check if client connection is re-started after a close */
+testcase TC_reconnect(integer idx := 0) runs on test_CT
+{
+	f_init();
+	f_init_one_srv(idx, ?);
+	f_sleep(2.0);
+
+	log("Disconnecting client-", idx);
+	f_disconnect(idx);
+
+	f_wait_client_connect(idx);
+	f_opcap_exp(tr_OPCAP_FILE_HDR(?), idx);
+	setverdict(pass);
+}
+
+/* capture a packet that's within the filter */
+testcase TC_capture() runs on test_CT
+{
+	f_init();
+	f_init_one_srv(0, ?);
+
+	for (var integer i := 0; i < 10; i := i + 1) {
+		var octetstring udp_payload;
+
+		/* we assume 1400 is low enough to avoid IP fragmentation */
+		udp_payload := f_rnd_octstring(f_rnd_int(1400));
+		f_trafic_pkt_ab(udp_payload);
+
+		f_opcap_exp_udp(udp_payload, 0);
+	}
+}
+
+/* wait for inbound client connections and reception of link header */
+testcase TC_multi_connect_rx_hdr() runs on test_CT
+{
+	f_init();
+	f_init_one_srv(0, ?);
+	f_vty_create_addl_connection(1);
+	f_init_one_srv(1, ?);
+	setverdict(pass);
+}
+
+/* ensure a packet that's within the filter is sent to secondary clients */
+testcase TC_multi_capture() runs on test_CT
+{
+	f_init();
+	f_init_one_srv(0, ?);
+	f_vty_create_addl_connection(1);
+	f_init_one_srv(1, ?);
+
+	for (var integer i := 0; i < 10; i := i + 1) {
+		var octetstring udp_payload;
+
+		/* we assume 1400 is low enough to avoid IP fragmentation */
+		udp_payload := f_rnd_octstring(f_rnd_int(1400));
+		f_trafic_pkt_ab(udp_payload);
+
+		/* expect packet to arrive on both simulated servers */
+		f_opcap_exp_udp(udp_payload, 0);
+		f_opcap_exp_udp(udp_payload, 1);
+	}
+}
+
+/* TODO: ensure a packet outside the filter is dropped */
+/* TODO: capture of truncated packet */
+/* TODO: stall the receive window */
+/* TODO: different link type (ethernet, not SLL) */
+
+
+control {
+	execute( TC_connect_rx_hdr() );
+	execute( TC_reconnect() );
+	execute( TC_capture() );
+	execute( TC_multi_connect_rx_hdr() );
+	execute( TC_multi_capture() );
+};
+
+
+};
diff --git a/pcap-client/gen_links.sh b/pcap-client/gen_links.sh
new file mode 100755
index 0000000..e459959
--- /dev/null
+++ b/pcap-client/gen_links.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+FILES+=" TCCEncoding_Functions.ttcn TCCEncoding.cc " # GSM 7-bit coding
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
+FILES="IPL4asp_Functions.ttcn  IPL4asp_PT.cc  IPL4asp_PT.hh IPL4asp_PortType.ttcn  IPL4asp_Types.ttcn  IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc  TELNETasp_PT.hh  TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="Osmocom_VTY_Functions.ttcn "
+FILES+="OPCAP_Types.ttcn OPCAP_Templates.ttcn "
+FILES+="OPCAP_CodecPort.ttcn OPCAP_CodecPort_CtrlFunct.ttcn OPCAP_CodecPort_CtrlFunctdef.cc OPCAP_Adapter.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/pcap-client/osmo-pcap-client.cfg b/pcap-client/osmo-pcap-client.cfg
new file mode 100644
index 0000000..89f1801
--- /dev/null
+++ b/pcap-client/osmo-pcap-client.cfg
@@ -0,0 +1,14 @@
+!
+! OsmoPCAPClient (UNKNOWN-dirty) configuration saved from vty
+!!
+!
+!
+line vty
+ no login
+!
+client
+ pcap device lo
+ pcap filter udp port 44423
+ pcap detect-loop 0
+ server ip 127.0.0.1
+ server port 5000

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/23878
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: If4a1072e75cb64f785d660e4c828c0f521d84b16
Gerrit-Change-Number: 23878
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/20210424/564630f4/attachment.htm>


More information about the gerrit-log mailing list