summaryrefslogtreecommitdiff
path: root/2017
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-11-01 22:17:36 +0100
committerHarald Welte <laforge@gnumonks.org>2017-11-01 22:17:36 +0100
commit1e8ba161bb1c4c3b42fef08072b371a9907431b7 (patch)
treea25febd0b48978df9e5814afe0d9564c45e6031d /2017
parent788c1e42d9ce280703a69ebdd110ea2dfae168fc (diff)
Add current version of ttcn3 slides for netdev 2.2
Diffstat (limited to '2017')
-rw-r--r--2017/ttcn-netdev2.2/ttcn3.adoc521
1 files changed, 521 insertions, 0 deletions
diff --git a/2017/ttcn-netdev2.2/ttcn3.adoc b/2017/ttcn-netdev2.2/ttcn3.adoc
new file mode 100644
index 0000000..3fd78c6
--- /dev/null
+++ b/2017/ttcn-netdev2.2/ttcn3.adoc
@@ -0,0 +1,521 @@
+TTCN-3 and Eclipse TITAN for testing protocol stacks
+====================================================
+:author: Harald Welte <laforge@gnumonks.org>
+:copyright: 2017 by Harald Welte (License: CC-BY-SA)
+:backend: slidy
+:max-width: 45em
+
+== Protocol Testing
+
+Important for:
+
+* conformance to specification
+* ensuring interoperability
+* network security
+* regression testing
+* performance
+
+== Protocol Testing
+
+No standard methodology, language, approach, tool
+
+* testing implementation against itself
+** works only for symmetric protocols
+** wouldn't cover lots of problems
+* testing against wireshark
+** wireshark often way more tolerant than spec
+* custom implementation
+** in Python (e.g. using scapy)
+** in Erlang (good binary encoder/decoder) or other languages
+* specific tools like packetdrill
+
+== Protocol Testing
+
+Personal story: During past years,
+
+* I implemented tons of [telecom] protocols / stacks at Osmocom.org
+* I was looking for better tools to help [automatic] testing
+** primarily functional testing (correctness / conformance)
+** not so much performance testing
+* I figured Ideal test tool would...
+** allow very productive and expressive way to describe encoding/decoding
+** allow very convenient pattern matching on incoming messages
+** allow exchange of messages asynchronously with implementation under test
+* I stumbled on TTCN-3 occasionally and investigated
+
+== The TTCN-3 Language
+
+* domain-specific language *just* for protocol conformance tests
+* TTCN history back to 1983 (!), TTCN-3 since 2000
+* used extensively in classic telecom sector (Ericsson, Nokia, etc.)
+* ETSI developed and published abstract test suites in TTCN-3 for
+** IPv6, SIP, DIAMETER, ePassports, Digital Mobiel Radio, 6LoWPAN
+* Other bodies published test suites for
+** CoAP, MQTT, MOST, AUTOSAR
+
+But: Until 2015, only proprietary tools / compilers :(
+
+== Eclipse TITAN
+
+* After TTCN-3 specification in 2000, Ericsson internally develops TTCN-3 toolchain
+* adopted for many Ericsson-internal testing of all kinds of products
+* proprietary software with commercial licenses
+* 300,000 lines of Java + 1.6 Million lines of C++
+* Released as Open Source as "Eclipse TITAN" in 2015
+** Not just TTCN-3 compiler, but also extensive documentations and many protocol modules, test ports as well as Eclipse IDE, Log file viewer/visualizer, etc.
+* `eclipse-titan` part of standard Debian / Ubuntu archive, only one apt-get away
+
+Great, we can finally use TTCN-3 in FOSS!
+
+== Eclipse TITAN compiler workflow
+
+[graphviz]
+----
+digraph G {
+ progra [label="Human Developer"];
+ ttcn3 [label="TTCN-3 source (ATS)"];
+ cpp [label="Generated C++ source"];
+ exec [label="Binary Executable (ETS)"];
+ tps [label="Other C++ sources, as needed"];
+ progra -> ttcn3 [label="writes code"];
+ ttcn3 -> cpp [label="ttcn3_compiler"];
+ cpp -> exec [label="GNU gcc / g++"];
+ tps -> cpp
+}
+----
+
+* TITAN actually _compiles_ into executable binaries, it is not using a VM or scripting
+** ATS: Abstract Test Suite (source code)
+** ETS: Executable Test Suite (executable code)
+
+== TTCN-3 Language Features (with TITAN)
+
+* comprehensive type system
+* parametric templates
+* variety of encoders/decoders
+* automatic / comprehensive logging framework
+* powerful program control statements
+* built-in notion of tests cases, test suites, verdicts, ...
+* runtime / executor for parallel test components + aggregating results
+
+== TTCN-3 Basic Types
+
+* Simple basic types such as `integer`, `float`, `boolen`
+* Basic string types such as `bitstring`, `octetstring`, `hexstring`, `charstring` (IA5) and `universal charstring` (UCS-4).
+* Structured Types `record`, `set`, `record of`, `set of`
+* Verdict type `verdicttype`
+** can have either value `none`, `pass`, `inconc`, `fail`, or `error`
+** verdict can only _deteriorate_ (`pass` -> `fail`) but never improve (`error` -> `pass`)
+** every test case implicitly has a verdict, no need to explicitly declare a variable of `verdicttype`
+
+== TTCN-3 Structured Types
+
+A structured type is an abstract type comprised of other types, whcih can be nested.
+An example for a `record` type (similar to a C-language `struct`) is shown below
+
+--------
+type record MyMessageType {
+ integer field1 optional<1>,
+ charstring field2,
+ boolean field3
+};
+--------
+<1> optional members may be present or not
+
+== TTCN-3 Union Type
+
+A union expresses a set of alternative types of which one alternative must be chosen.
+
+--------
+type union MyMessageUnion {
+ integer field1,
+ charstring field2,
+};
+--------
+
+Difference to C-language union: `ischosen()` can be used to learn which of the union members is
+chosen/defined!
+
+
+== Not-used and omit
+
+* until a variable or field of structured type is assigned, it is _unbound_
+* whenever a _value_ is expected, TTCN-3 runtime will create an error for _unbound_
+* in case of absence of optional fields, explicit `omit` value must be assigned!
+
+== Sub-typing
+
+Sub-typing can be used to further constrain a given type. Typical examples include constrained number ranges,
+and string patterns
+
+--------
+type integer MyIntRange (1..100);
+type integer MyIntRange8 (0..infinity);
+type charstring MyCharRange (”k”..”w");
+type charstring SideType (”left”, ”right”);
+type integer MyIntListRange (1..5,7,9);
+type record length(0..10) of integer RecOfInt;
+type charstring CrLfTermStrin (pattern ”*\r\n”);
+--------
+
+== Templates
+
+* Matching incoming messages against some kind of specification is one of the most common tasks in testing protocols
+** some expected fields are static (message type)
+** some expected fields are known (source address)
+** some fields are chosen by sender (some identifier)
+** some fields we don't care (optional headers that may or may not be present)
+* TTCN-3 Templates provide elegant solution for this, avoiding any explicit code to be written
+** templates can even be parametric, i.e. they can be instantiated with "arguments"
+* templates can also be used for sending messages, if they are fully specified/qualified
+
+== Templates
+
+--------
+// Value list template
+template charstring tr_SingleABorC := (”A”, ”B”, ”C”);
+--------
+
+--------
+// Value range
+template float tr_NearPi := (3.14 .. 3.15);
+template integer tr_FitsToOneByte := (0 .. 255);
+template integer tr_GreaterThanZero := (1 .. infinity);
+--------
+
+--------
+// Intermixed value list and range matching
+template integer tr_Intermixed := ((0..127), 200, 255);
+--------
+
+== Matching inside values
+
+--------
+// Using any element matching inside a bitstring value
+// Last 2 bits can be '0' or '1'
+template bitstring tr_AnyBSValue := ’101101??’B;
+--------
+
+--------
+// Matches charstrings with the first character "a"
+// and the last one "z"
+template charstring tr_0 := pattern "a*z";
+--------
+
+* more capabilities using `complement`, `ifpresent`, `subset`, `superset`, `permutation` constructs not
+ covered here
+
+
+== Parametric Templates
+
+See below for an example of a parametric template:
+
+--------
+type record MyMessageType {
+ integer field1 optional,
+ charstring field2,
+ boolean field3
+};
+
+template MyMessageType trMyTemplte(boolean pl_param) := {
+ field1 : = ?, // present, but any value
+ field2 : = (”B”, ”O”, ”Q”) ,
+ field3 := pl_param
+};
+--------
+
+The built-in `match()` function can be used to check if a given value matches a given template. Some TTCN-3
+statements such as `receive()` have built-in capabilities for template matching, avoiding even the explicit
+call of `match()` in many cases.
+
+== Template Hierarchy
+
+Using modified templates, one can build a hierarchy of templates: From the specific to the unspecific
+
+----
+template MyMsgType t_MyMsgAny := {
+ msg_type := ?,
+ foo := bar
+};
+
+template MyMsgType t_MyMsg23 modifies t_MyMsgAny := {
+ msg_type := 23,
+};
+----
+where
+
+* _t_MyMsgAny_ matches a message with any message type and "foo=bar", while
+* _t_MMyMsg23_ matches only those that have "foo=bar" and "msg_type=23"
+
+== Encoders/Decoders
+
+* type system, templates, matching are all nice and great, but we need to get data from wire format into
+ TTCN-3 abstract types
+* TTTCN-3 specifies importing of formal schema definitios, such as ASN.1, IDL, XSD (XML) and JSON
+* TITAN has additional codecs for those (many) protocols that lack formal syntax
+** `raw` codec for binary protocols (e.g. GTP)
+** `text` codec for text based protocols (e.g. HTTP, MGCP, IMAP, ...)
+* codecs allow you to _express/describe_ the format (declarative programming) rather than the usual imperative approach
+
+== TITAN raw codec: UDP Example
+
+How to express an UDP header using TITAN raw codec
+
+--------
+type integer LIN2_BO_LAST (0..65535) with {
+ variant ”FIELDLENGTH(16), COMP(nosign), BYTEORDER(last)”
+};
+type record UDP_header {
+ LIN2_BO_LAST srcport,
+ LIN2_BO_LAST dstport,
+ LIN2_BO_LAST len,
+ LIN2_BO_LAST cksum
+} with { variant ”FIELDORDER(msb)” };
+type record UDP packet {
+ UDP_header header
+ octetstring payload
+} with {
+ variant (header) ”LENGTHTO(header, payload), LENGTHINDEX(len)”
+};
+--------
+
+== TITAN raw codec: GTP Example
+
+How to express an GTP header using TITAN raw codec
+
+--------
+type record GRE_Header {
+ BIT1 csum_present,
+ BIT1 rt_present,
+ BIT1 key_present,
+ ...
+ OCT2 protocol_type,
+ OCT2 checksum optional,
+ OCT2 offset optional,
+ OCT4 key otional,
+ ...
+} with {
+ variant (checksum) "PRESENCE(csum_present='1', rt_present='1'B)"
+ variant (offset) "PRESENCE(csum_present='1'B, rt_present='1'B)"
+ variant (key) "PRESENCE(key_present='1'B)"
+}
+--------
+
+
+== TITAN text codec: MGCP Example
+
+--------
+type charstring MgcpVerb ("EPCF", "CRCX", "MDCX", "DLCX", "RQNT", "NTFY",
+ "AUEP", "AUCX", "RSIP") with {
+ variant "TEXT_CODING(,convert=upper_case,,case_insensitive)"
+};
+type charstring MgcpTransId (pattern "\d#(1,9)");
+type charstring MgcpEndpoint (pattern "*@*");
+type charstring MgcpVersion (pattern "\d.\d") with {
+ variant "BEGIN('MGCP ')"
+};
+type record MgcpCommandLine {
+ MgcpVerb verb,
+ MgcpTransId trans_id,
+ MgcpEndpoint ep,
+ MgcpVersion ver
+} with {
+ variant "SEPARATOR(' ', '[\t ]+')"
+ variant "END('\r\n', '([\r\n])|(\r\n)')"
+};
+--------
+
+== Program Control Statements
+
+* `if` / `else` like in C
+* `select` statement similar to C `switch`
+* `for`, `while`, `do-while` loops like in C
+* `goto` and `label`
+* `break` and `continue` like in C
+
+== Abstract Communications Operations
+
+* TTCN-3 test suites communicate with _implementation under test_ through abstract TestPorts
+** TestPorts can be implemented in TTCN-3 or C++ and linked in
+** TestPorts must be _connected_ before using send/receive operaitons
+** TITAN provides TestPorts for e.g. packet socket, IP/UDP/TCP/SCTP socket, ...
+* `<port>.send(<ValueRef>)` performs non-blocking send
+** Literal value, constant, variable, specific value template, ...
+* `<port>.receive(<TemplateRef>)` or `<port>.receive` performs blocking receive
+** literal value, constant, variable, template (with matching!), inline template
+
+'... but if receive blocks, how can we wait for any of N events?
+
+== Program Control and Behavior
+
+* program statements are executed in order
+* blocking statements block the execution of the component
+* occurrence of unexpected event may cause infinite blocking
+
+----
+// x must be the first on queue P, y the second
+P.receive(x); // Blocks until x appears on top of queue P
+P.receive(y); // Blocks until y appears on top of queue P
+// When y arrives first then P.receive(x) blocks -> error
+----
+
+This is what leads to the `alt` statement:
+`alt` declares a seto alternatives covering all events, which
+
+* can happen: expected messages, timeouts, ...
+* must not happen: unexpected faulty messages, no message received, ...
+* all alternatives inside `alt` are blocking operations
+
+== The `alt` statement
+
+----
+P.send(req)
+T.start;
+// ...
+alt {
+[] P.receive(resp) { /* actions to do and exit alt */ }
+[] any port.receive { /* handle unexpected event */ }
+[] T.timeout { /* handle timer expiry and exit */ }
+}
+----
+
+* [] is guard condition enables or disables the alternative
+** usually empty `[]` equals `[true]`
+** can contain a condition like `[x > 0]`
+** very good for e.g. state machines to activate some alternatives only in certain states while others may
+occur in any state
+
+
+== The `alt` and `repeat` statements
+
+The `repeat` statement
+
+* takes a new snapshot and re-evaluates the alt statement
+* can appear as last statement in statement blocks of statements
+
+----
+P.send(req)
+T.start;
+alt {
+ [] P.receive(resp) { /* actions to do and exit alt */ }
+ [] P.receive(keep_alive) { /* handle keep alive message */
+ repeat }
+ [] any port.receive { /* handle unexpected event */ }
+ [] T.timeout { /* handle timer expiry and exit */ }
+}
+----
+
+== TTCN-3 modules
+
+TTCN-3 code is written in _modules_
+
+* a test suite consists of one or more modules
+* a module contains _module definitions_ and an optional _control part_
+** _parameters_ (automatically configurable via config file)
+** definition of _data types_, _constants_, _templates_
+** definition of _communications ports_
+** definition of _test components_, _functions_ _altstesp_ and _test cases_
+** _control part_ determines default order/execution of test cases
+* modules can import from each other (think in python terms)
+
+== Examples
+
+Let's have a look at some real-world examples and do a bit of a walk-through
+before continuing with the slides...
+
+== Logging
+
+* TITAN runtime contains extensive logging framework
+* config file determines log level for various different subsystems
+** e.g. any encode, decode, receive, transmit operations logged
+** timer starts, expirations
+** any changes to test case verdict
+* explicit logging from code by use of `log()` built-in function
+* `ttcn3_logformat` tool for pretty-printing log files
+* `ttcn3_logmerge` tool for merging/splicing multiple logs
+* log plugins e.g. for generating JUnit-XML available
+** facilitates easy reporting / integration to Jenkins or other CI
+
+== Logging
+
+Log file format example:
+
+----
+// abstract data type before encode
+13:30:41.243536 Sent on GTPC to system @GTP_CodecPort.Gtp1cUnitdata : { peer := { connId := 1, remName := "127.0.23.1", remPort := 2123 }, gtpc := { pn_bit := '0'B, s_bit := '1'B, e_bit := '0'B, spare := '0'B, pt := '1'B, version := '001'B, messageType := '01'O, lengthf := 0, teid := '00000000'O, opt_part := { sequenceNumber := '3AAC'O, npduNumber := '00'O, nextExtHeader := '00'O, gTPC_extensionHeader_List := omit }, gtpc_pdu := { echoRequest := { private_extension_gtpc := omit } } } }
+
+// 'msg' contains encoded binary data actually sent via socket
+13:30:41.243799 Outgoing message was mapped to @IPL4asp_Types.ASP_SendTo : { connId := 1, remName := "127.0.23.1", remPort := 2123, proto := { udp := { } }, msg := '32010004000000003AAC0000'O }
+----
+
+== Logging
+
+The same log file lines if run through `ttcn3_logformat`
+
+----
+13:30:41.243536 Sent on GTPC to system @GTP_CodecPort.Gtp1cUnitdata : {
+ peer := {
+ connId := 1,
+ remName := "127.0.23.1",
+ remPort := 2123
+ },
+ gtpc := {
+ pn_bit := '0'B,
+ s_bit := '1'B,
+ e_bit := '0'B,
+ spare := '0'B,
+ pt := '1'B,
+ version := '001'B,
+ messageType := '01'O,
+ lengthf := 0,
+ teid := '00000000'O,
+ opt_part := {
+ sequenceNumber := '3AAC'O,
+ npduNumber := '00'O,
+ nextExtHeader := '00'O,
+ gTPC_extensionHeader_List := omit
+ },
+ gtpc_pdu := {
+ echoRequest := {
+ private_extension_gtpc := omit
+ }
+ }
+ }
+}
+13:30:41.243799 Outgoing message was mapped to @IPL4asp_Types.ASP_SendTo : {
+ connId := 1,
+ remName := "127.0.23.1",
+ remPort := 2123,
+ proto := {
+ udp := { }
+ },
+ msg := '32010004000000003AAC0000'O
+}
+----
+
+
+== Existing TITAN Source
+
+* Protocol encoding/decoding
+** BSSAP+, BSSGP, BSSMAP, CoAP, DSS1, DUA, EAP, GRE, GTP, HTTP, ISUP, LLC, M2PA, M2UA, MQTT, MongoDB, NDP, NS,
+ NTAF, ROSE, SCTP, SDP, SNDCP, STOMP, STUN, SUA, TLS, WTP, DNS, IP, SMPP, SNMP, IKEv2, DHCP, PPP, RTP, TCP,
+ UDP, XMPP, DHCPv6, SMTP, ICMP, RTSP, ICMPv6, DIAMETER, FrameRelay, ProtoBuff, IUA, L2TP, M3UA, MIME,
+ WebSocket, H.248, IMAP, IPsec, SRTP, MSRP, ICAP, RADIUS
+* Protocol Emulation
+** M3UA, SCCP, SUA
+* Test Ports
+** GPIO, MTP3, Serial, SocketCAN, SCTP, SIP, HTTP, Telnet, UDP, pcap file, pipe, SQL, TCP, SUNRPC, SSH, STDINOUT, sockets, LDAP
+
+
+== Further Reading
+
+* Ericsson TTCN-3 tutorial http://www.ttcn-3.org/files/TTCN3_P.pdf
+* An Introduction to TTCN-3, 2nd Edition <http://www.wiley.com/go/willcock_TTCN-3_2e>
+* Modules https://github.com/eclipse
+* More Modules http://git.eclipse.org/
+* Debian https://packages.debian.org/search?keywords=eclipse-titan
+* Ubuntu https://packages.ubuntu.com/search?keywords=eclipse-titan
+
+== EOF
+
+End of File
personal git repositories of Harald Welte. Your mileage may vary