You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2019/01/23 16:13:42 UTC

[incubator-plc4x] branch develop updated: - Added a merged dfdl schema joining TPKT, COTP and S7 schema.develop - Started creating a testsuite for this merged schema.

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new d3d2cde  - Added a merged dfdl schema joining TPKT, COTP and S7 schema.develop - Started creating a testsuite for this merged schema.
d3d2cde is described below

commit d3d2cde21cc1726cbae16ace2452f5d63d9c7d0d
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Jan 23 17:13:37 2019 +0100

    - Added a merged dfdl schema joining TPKT, COTP and S7 schema.develop
    - Started creating a testsuite for this merged schema.
---
 .../src/main/dfdl/daffodil-built-in-catalog.xml    |   4 +-
 .../apache/plc4x/protocols/cotp-protocol.dfdl.xsd  |   8 +-
 .../protocols/s7-full-stack-protocol.dfdl.xsd      | 863 +++++++++++++++++++++
 protocols/src/main/java/.keepMe                    |   4 +
 .../plc4x/protocols/S7FullStackProtocolTest.java   |  31 +
 .../plc4x/protocols/s7-full-stack-protocol.tdml    | 704 +++++++++++++++++
 6 files changed, 1609 insertions(+), 5 deletions(-)

diff --git a/protocols/src/main/dfdl/daffodil-built-in-catalog.xml b/protocols/src/main/dfdl/daffodil-built-in-catalog.xml
index db26ac7..ae2a712 100644
--- a/protocols/src/main/dfdl/daffodil-built-in-catalog.xml
+++ b/protocols/src/main/dfdl/daffodil-built-in-catalog.xml
@@ -20,6 +20,8 @@
        uri="org/apache/plc4x/protocols/tpkt-protocol.dfdl.xsd"/>
   <uri name="http://plc4x.apache.org/cotp"
        uri="org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd"/>
-  <uri name="http://plc4x.apache.org/cotp"
+  <uri name="http://plc4x.apache.org/s7"
        uri="org/apache/plc4x/protocols/s7-protocol.dfdl.xsd"/>
+  <uri name="http://plc4x.apache.org/s7-full"
+       uri="org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd"/>
 </catalog>
\ No newline at end of file
diff --git a/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd b/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd
index 14cbfb3..665c4b1 100644
--- a/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd
+++ b/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd
@@ -57,7 +57,7 @@
         <xs:restriction base="xs:unsignedShort"/>
     </xs:simpleType>
 
-    <xs:simpleType name="tpduType">
+    <xs:simpleType name="CotpTpduType">
         <xs:restriction base="xs:unsignedByte">
             <xs:enumeration id="tpduTypeConnectionRequest" value="224">
                 <xs:annotation>
@@ -92,7 +92,7 @@
         </xs:restriction>
     </xs:simpleType>
 
-    <xs:simpleType name="parameterType">
+    <xs:simpleType name="CotpParameterType">
         <xs:restriction base="xs:unsignedByte">
             <xs:enumeration value="192">
                 <xs:annotation>
@@ -134,7 +134,7 @@
         <xs:sequence>
             <!-- Length of the COTP header data -->
             <xs:element name="headerLength" type="cotp:byte"/>
-            <xs:element name="type" type="cotp:tpduType"/>
+            <xs:element name="type" type="cotp:CotpTpduType"/>
             <xs:choice dfdl:choiceDispatchKey="{type}">
                 <xs:element dfdl:choiceBranchKey="224" ref="cotp:CotpTpduConnectionRequest"/>
                 <xs:element dfdl:choiceBranchKey="208" ref="cotp:CotpTpduConnectionResponse"/>
@@ -229,7 +229,7 @@
                 <xs:element name="parameter" maxOccurs="unbounded">
                     <xs:complexType>
                         <xs:sequence>
-                            <xs:element name="type" type="cotp:parameterType"/>
+                            <xs:element name="type" type="cotp:CotpParameterType"/>
                             <xs:element name="parameterLength" type="cotp:byte"/>
                             <xs:choice dfdl:choiceDispatchKey="{type}">
                                 <xs:element dfdl:choiceBranchKey="192" ref="cotp:CotpParameterTpduSize"/>
diff --git a/protocols/src/main/dfdl/org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd b/protocols/src/main/dfdl/org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd
new file mode 100644
index 0000000..f220055
--- /dev/null
+++ b/protocols/src/main/dfdl/org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd
@@ -0,0 +1,863 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+           xmlns:s7f="http://plc4x.apache.org/s7-full"
+           xmlns:fn="http://www.w3.org/2005/xpath-functions"
+           targetNamespace="http://plc4x.apache.org/s7-full">
+
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/">
+            <dfdl:defineVariable name="messageType" type="xs:string"/>
+            <dfdl:defineFormat name="s7FullFormat">
+                <dfdl:format representation="binary"
+                             binaryNumberRep="binary"
+                             byteOrder="bigEndian"
+                             lengthKind="implicit" lengthUnits="bytes" length="0"
+                             occursCountKind="implicit"
+                             textOutputMinLength="0"
+                             alignment="1" alignmentUnits="bits"
+                             leadingSkip="0" trailingSkip="0"
+                             textPadKind="none" ignoreCase="no"
+                             encoding="utf-8" truncateSpecifiedLengthString="no"
+                             initiator="" terminator=""
+                             sequenceKind="ordered" separator=""
+                             escapeSchemeRef="" initiatedContent="no"/>
+            </dfdl:defineFormat>
+            <dfdl:format ref="s7f:s7FullFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <!--
+
+        Simple type definition.
+
+    -->
+
+    <xs:simpleType name="bit" dfdl:lengthUnits="bits" dfdl:length="1" dfdl:lengthKind="explicit">
+        <xs:restriction base="xs:boolean"/>
+    </xs:simpleType>
+
+    <xs:simpleType name="byte" dfdl:lengthUnits="bytes" dfdl:length="1" dfdl:lengthKind="explicit">
+        <xs:restriction base="xs:unsignedByte"/>
+    </xs:simpleType>
+
+    <xs:simpleType name="short" dfdl:lengthUnits="bytes" dfdl:length="2" dfdl:lengthKind="explicit">
+        <xs:restriction base="xs:unsignedShort"/>
+    </xs:simpleType>
+
+    <xs:simpleType name="hexByte" dfdl:lengthUnits="bytes" dfdl:length="1" dfdl:lengthKind="explicit">
+        <xs:restriction base="xs:hexBinary"/>
+    </xs:simpleType>
+
+    <!--
+
+        TPKT - Iso-On-TCP
+
+    -->
+
+    <xs:element name="TpktMessage" type="s7f:TpktMessageType"/>
+
+    <xs:complexType name="TpktMessageType">
+        <xs:sequence>
+            <!-- TPKT Magic Byte always 0x03 -->
+            <xs:element name="magicByte" type="s7f:byte">
+                <xs:annotation>
+                    <xs:appinfo source="http://www.ogf.org/dfdl/">
+                        <dfdl:assert message="Magic number was not 0x03."
+                                     test="{. eq 3}"/>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="reserved" type="s7f:byte"/>
+            <xs:element name="length" type="s7f:short"/>
+            <xs:element name="userData" type="s7f:CotpMessageType"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!--
+
+        ISO 8073/X.224 - ISO-TP - COTP - Connection-Oriented Transport Protocol Messages
+
+    -->
+
+    <xs:simpleType name="CotpTpduType">
+        <xs:restriction base="xs:unsignedByte">
+            <xs:enumeration id="tpduTypeConnectionRequest" value="224">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">ConnectionRequest</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration id="tpduTypeConnectionResponse" value="208">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">ConnectionResponse</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="128">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">DisconnectRequest</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="192">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">DisconnectResponse</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="112">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">Error</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="240">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">Data</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="CotpParameterType">
+        <xs:restriction base="xs:unsignedByte">
+            <xs:enumeration value="192">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">TpduSize</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="193">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">CallingTsap</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="194">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">CalledTsap</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="195">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">Checksum</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+            <xs:enumeration value="224">
+                <xs:annotation>
+                    <xs:appinfo source="http://plc4x.apache.org/">DisconnectAdditionalInformation</xs:appinfo>
+                </xs:annotation>
+            </xs:enumeration>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="CotpMessageType">
+        <xs:sequence>
+            <!-- Length of the COTP header data -->
+            <xs:element name="headerLength" type="s7f:byte"/>
+            <xs:element name="type" type="s7f:CotpTpduType"/>
+            <xs:choice dfdl:choiceDispatchKey="{type}">
+                <xs:element dfdl:choiceBranchKey="224" ref="s7f:CotpTpduConnectionRequest"/>
+                <xs:element dfdl:choiceBranchKey="208" ref="s7f:CotpTpduConnectionResponse"/>
+                <xs:element dfdl:choiceBranchKey="128" ref="s7f:CotpTpduDisconnectRequest"/>
+                <xs:element dfdl:choiceBranchKey="192" ref="s7f:CotpTpduDisconnectResponse"/>
+                <xs:element dfdl:choiceBranchKey="112" ref="s7f:CotpTpduError"/>
+                <xs:element dfdl:choiceBranchKey="240" ref="s7f:CotpTpduData"/>
+            </xs:choice>
+            <xs:element name="userData" type="s7f:S7MessageType" minOccurs="0"
+                        dfdl:occursCountKind="expression" dfdl:occursCount="{if((../../length - (../headerLength + 1)) gt 0) then 1 else 0}"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:element name="CotpTpduConnectionRequest">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="destinationReference" type="s7f:short"/>
+                <xs:element name="sourceReference" type="s7f:short"/>
+                <xs:element name="protocolClass" type="s7f:byte"/>
+                <xs:element ref="s7f:parameters" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 6}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../../headerLength gt 6) then 1 else 0}"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpTpduConnectionResponse">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="destinationReference" type="s7f:short"/>
+                <xs:element name="sourceReference" type="s7f:short"/>
+                <xs:element name="protocolClass" type="s7f:byte"/>
+                <xs:element ref="s7f:parameters" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 6}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../../headerLength gt 6) then 1 else 0}"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpTpduDisconnectRequest">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="destinationReference" type="s7f:short"/>
+                <xs:element name="sourceReference" type="s7f:short"/>
+                <xs:element name="disconnectReason" type="s7f:byte"/>
+                <xs:element ref="s7f:parameters" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 6}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../../headerLength gt 6) then 1 else 0}"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpTpduDisconnectResponse">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="destinationReference" type="s7f:short"/>
+                <xs:element name="sourceReference" type="s7f:short"/>
+                <xs:element ref="s7f:parameters" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 5}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../../headerLength gt 5) then 1 else 0}"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpTpduError">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="destinationReference" type="s7f:short"/>
+                <xs:element name="rejectCause" type="s7f:byte"/>
+                <xs:element ref="s7f:parameters" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 4}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../../headerLength gt 4) then 1 else 0}"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpTpduData">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="endOfTransmission" type="xs:unsignedInt"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="1"/>
+                <xs:element name="tpduRef" type="xs:unsignedInt"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="7"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="parameters">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="parameter" maxOccurs="unbounded">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="type" type="s7f:CotpParameterType"/>
+                            <xs:element name="parameterLength" type="s7f:byte"/>
+                            <xs:choice dfdl:choiceDispatchKey="{type}">
+                                <xs:element dfdl:choiceBranchKey="192" ref="s7f:CotpParameterTpduSize"/>
+                                <xs:element dfdl:choiceBranchKey="193" ref="s7f:CotpParameterCallingTsap"/>
+                                <xs:element dfdl:choiceBranchKey="194" ref="s7f:CotpParameterCalledTsap"/>
+                                <xs:element dfdl:choiceBranchKey="195" ref="s7f:CotpParameterChecksum"/>
+                                <xs:element dfdl:choiceBranchKey="224"
+                                            ref="s7f:CotpParameterDisconnectAdditionalInformation"/>
+                            </xs:choice>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpParameterTpduSize">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="tpduSize" type="s7f:byte"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpParameterCallingTsap">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="tsapId" type="s7f:short"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpParameterCalledTsap">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="tsapId" type="s7f:short"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpParameterChecksum">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="checksum" type="s7f:byte"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="CotpParameterDisconnectAdditionalInformation">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="data" type="xs:hexBinary"
+                            dfdl:byteOrder="bigEndian" dfdl:lengthUnits="bytes" dfdl:lengthKind="explicit"
+                            dfdl:length="{../../parameterLength}"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <!--
+
+        S7 Types
+
+    -->
+
+    <xs:complexType name="S7MessageType">
+        <xs:sequence>
+            <!-- S7 Magic Byte always 0x32 -->
+            <xs:element name="magicByte" type="s7f:byte">
+                <xs:annotation>
+                    <xs:appinfo source="http://www.ogf.org/dfdl/">
+                        <dfdl:assert message="Magic number was not 0x32."
+                                     test="{. eq 50}"/>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="type" type="s7f:byte"/>
+            <!--
+                Unfortunately the response for a CPU Functions request follows the rules of a
+                response, however has the header structure of a request
+                (no error code or error class). As mapping to the same type is not allowed,
+                we map to strings and use that as choice-key.
+            -->
+            <xs:choice dfdl:choiceDispatchKey="{
+                                if(type eq 1) then 'request'
+                                else if(type eq 3) then 'response'
+                                else if(type eq 7) then 'response'
+                                else 'unknown'
+                            }">
+                <xs:element dfdl:choiceBranchKey="request" ref="s7f:S7RequestMessage"/>
+                <xs:element dfdl:choiceBranchKey="response" ref="s7f:S7ResponseMessage"/>
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:element name="S7RequestMessage">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- Reserved value always 0x0000 -->
+                <xs:element name="reserved" type="s7f:short" fixed="0"/>
+                <xs:element name="tpduReference" type="s7f:short"/>
+                <xs:element name="parametersLength" type="s7f:short"/>
+                <xs:element name="payloadsLength" type="s7f:short"/>
+                <xs:element name="parameters" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../parametersLength}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="parameter" maxOccurs="unbounded">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:element name="type" type="s7f:byte"/>
+                                        <xs:choice dfdl:choiceDispatchKey="{type}">
+                                            <xs:element dfdl:choiceBranchKey="240"
+                                                        ref="s7f:S7GeneralParameterSetupCommunication"/>
+                                            <xs:element dfdl:choiceBranchKey="0"
+                                                        ref="s7f:SS7RequestParameterCPUService"/>
+                                            <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7RequestParameterReadVar"/>
+                                            <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7RequestParameterWriteVar"/>
+                                        </xs:choice>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <!--
+                   As we might be outputting an empty payload block for a parameter that might not have a payload,
+                   we have to output this element if the parameters are not empty. The case that the payloads are
+                   not empty but the parameters are can't happen during normal operation.
+               -->
+                <xs:element name="payloads" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../payloadsLength}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <!--
+                                For every parameter we'll be outputting a payload block, even if this might be empty.
+                                This is required in order to find the matching parameter for every payload we might
+                                be having. We need to match these as otherwise we couldn't determin the type of a
+                                payload as this has no type information and we need to be able to access the number
+                                of items for a read/write request in order to process the correct number of items in
+                                the payload.
+                            -->
+                            <xs:element name="payload" maxOccurs="unbounded"
+                                        dfdl:occursCountKind="expression"
+                                        dfdl:occursCount="{fn:count(../../parameters[1]/parameter)}">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:choice dfdl:choiceDispatchKey="{../../parameters[1]/parameter[dfdl:occursIndex()]/type}">
+                                            <xs:element dfdl:choiceBranchKey="240"
+                                                        ref="s7f:S7GeneralPayloadSetupCommunication"/>
+                                            <xs:element dfdl:choiceBranchKey="0" ref="s7f:S7RequestPayloadCpuServices"/>
+                                            <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7RequestPayloadReadVar"/>
+                                            <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7RequestPayloadWriteVar"/>
+                                        </xs:choice>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7ResponseMessage">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- Reserved value always 0x0000 -->
+                <xs:element name="reserved" type="s7f:short" fixed="0"/>
+                <xs:element name="tpduReference" type="s7f:short"/>
+                <xs:element name="parametersLength" type="s7f:short"/>
+                <xs:element name="payloadsLength" type="s7f:short"/>
+                <!-- UserData (type 7) responses don't have the error class and code -->
+                <xs:element name="errorClass" type="s7f:byte" minOccurs="0"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{if(../../type eq 3) then 1 else 0}"/>
+                <xs:element name="errorCode" type="s7f:byte" minOccurs="0"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{if(../../type eq 3) then 1 else 0}"/>
+                <xs:element name="parameters" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../parametersLength}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="parameter" maxOccurs="unbounded">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:element name="type" type="s7f:byte"/>
+                                        <xs:choice dfdl:choiceDispatchKey="{type}">
+                                            <xs:element dfdl:choiceBranchKey="240"
+                                                        ref="s7f:S7GeneralParameterSetupCommunication"/>
+                                            <xs:element dfdl:choiceBranchKey="0"
+                                                        ref="s7f:S7ResponseParameterCPUService"/>
+                                            <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7ResponseParameterReadVar"/>
+                                            <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7ResponseParameterWriteVar"/>
+                                        </xs:choice>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <!--
+                    As we might be outputting an empty payload block for a parameter that might not have a payload,
+                    we have to output this element if the parameters are not empty. The case that the payloads are
+                    not empty but the parameters are can't happen during normal operation.
+                -->
+                <xs:element name="payloads" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../payloadsLength}"
+                            dfdl:occursCountKind="expression"
+                            dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <!--
+                                For every parameter we'll be outputting a payload block, even if this might be empty.
+                                This is required in order to find the matching parameter for every payload we might
+                                be having. We need to match these as otherwise we couldn't determin the type of a
+                                payload as this has no type information and we need to be able to access the number
+                                of items for a read/write request in order to process the correct number of items in
+                                the payload.
+                            -->
+                            <xs:element name="payload" maxOccurs="unbounded"
+                                        dfdl:occursCountKind="expression"
+                                        dfdl:occursCount="{fn:count(../../parameters[1]/parameter)}">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:choice
+                                            dfdl:choiceDispatchKey="{../../parameters[1]/parameter[dfdl:occursIndex()]/type}">
+                                            <xs:element dfdl:choiceBranchKey="240"
+                                                        ref="s7f:S7GeneralPayloadSetupCommunication"/>
+                                            <xs:element dfdl:choiceBranchKey="0" ref="s7f:S7ResponsePayloadCpuServices"/>
+                                            <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7ResponsePayloadReadVar"/>
+                                            <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7ResponsePayloadWriteVar"/>
+                                        </xs:choice>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <!--
+
+        Parameters.
+
+    -->
+
+    <xs:element name="S7GeneralParameterSetupCommunication">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- Reserved value always 0x00 -->
+                <xs:element name="reserved" type="s7f:byte" fixed="0"/>
+                <xs:element name="maxAmqCaller" type="s7f:short"/>
+                <xs:element name="maxAmqCallee" type="s7f:short"/>
+                <xs:element name="pduLength" type="s7f:short"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="SS7RequestParameterCPUService">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- Fixed header 0x0112 274 -> -->
+                <xs:element name="header" type="s7f:short"/><!-- fixed="274"-->
+                <xs:element name="length" type="s7f:byte"/><!-- fixed="4"-->
+                <!-- Request: 0x11 -> 17 -->
+                <xs:element name="typeCode" type="s7f:byte"/><!-- fixed="17"-->
+                <!-- First 4 bits: Request 0x40, last 4 bits: Function Group 0x04 = 0x44 -> 68 -->
+                <xs:element name="functionGroup" type="s7f:byte"/><!-- fixed="68"-->
+                <!-- READ SSL = 0x01 -->
+                <xs:element name="subFunctionGroup" type="s7f:byte"/><!-- fixed="1"-->
+                <xs:element name="sequenceNumber" type="s7f:byte"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7ResponseParameterCPUService">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- Fixed header 0x0112 274 -> -->
+                <xs:element name="header" type="s7f:short"/><!-- fixed="274"-->
+                <xs:element name="paramLength" type="s7f:byte"/><!-- fixed="8"-->
+                <!-- Response: 0x12 -> 18 -->
+                <xs:element name="typeCode" type="s7f:byte"/><!-- fixed="18"-->
+                <!-- First 4 bits: Response 0x80, last 4 bits: Function Group 0x04 = 0x84 -> 132 -->
+                <xs:element name="functionGroup" type="s7f:byte"/><!-- fixed="132"-->
+                <!-- READ SSL = 0x01 -->
+                <xs:element name="subFunctionGroup" type="s7f:byte"/><!-- fixed="1"-->
+                <xs:element name="sequenceNumber" type="s7f:byte"/>
+                <xs:element name="dataUnitReferenceNumber" type="s7f:byte"/>
+                <xs:element name="lastDataUnit" type="s7f:byte"/>
+                <xs:element name="error" type="s7f:short"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7RequestParameterReadVar">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="numItems" type="s7f:byte"/>
+                <xs:element name="items" minOccurs="0"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{if(../numItems gt 0) then 1 else 0}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="item" minOccurs="0"
+                                        dfdl:occursCountKind="expression" dfdl:occursCount="{../../numItems}">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:element name="type" type="s7f:byte"/>
+                                        <xs:choice dfdl:choiceDispatchKey="{type}">
+                                            <xs:element dfdl:choiceBranchKey="18"
+                                                        ref="s7f:S7RequestParameterReadVarAnyItem"/>
+                                        </xs:choice>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7RequestParameterReadVarAnyItem">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="paramLength" type="s7f:byte"/><!-- fixed="10"-->
+                <!-- Addressing Mode: Any 0x10 -> 16 -->
+                <xs:element name="addressingMode" type="s7f:byte"/><!-- fixed="16"-->
+                <xs:element name="dataType" type="s7f:byte"/>
+                <xs:element name="numElements" type="s7f:short"/>
+                <xs:element name="dataBlockNumber" type="s7f:short"/>
+                <xs:element name="memoryArea" type="s7f:byte"/>
+                <!--
+                 The next 3 bytes (24 bits) contain the byte- and bit-offset,
+                 were the last byte contains the bit-offset in the last 3 bits
+                 and the byteOffset is encoded in the higher level 21 bits
+                -->
+                <xs:element name="byteOffset" type="xs:unsignedInt"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="21"/>
+                <xs:element name="bitOffset" type="xs:unsignedInt"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="3"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7ResponseParameterReadVar">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="numItems" type="s7f:byte"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7RequestParameterWriteVar">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="numItems" type="s7f:byte"/>
+                <xs:element name="items" minOccurs="0"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{if(../numItems gt 0) then 1 else 0}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="item" minOccurs="0"
+                                        dfdl:occursCountKind="expression" dfdl:occursCount="{../../numItems}">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:element name="type" type="s7f:byte"/>
+                                        <xs:choice dfdl:choiceDispatchKey="{type}">
+                                            <xs:element dfdl:choiceBranchKey="18"
+                                                        ref="s7f:S7RequestParameterWriteVarAnyItem"/>
+                                        </xs:choice>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7RequestParameterWriteVarAnyItem">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="itemLength" type="s7f:byte"/><!-- fixed="10"-->
+                <!-- Addressing Mode: Any 0x10 -> 16 -->
+                <xs:element name="addressingMode" type="s7f:byte"/><!-- fixed="16"-->
+                <xs:element name="dataType" type="s7f:byte"/>
+                <xs:element name="numElements" type="s7f:short"/>
+                <xs:element name="dataBlockNumber" type="s7f:short"/>
+                <xs:element name="memoryArea" type="s7f:byte"/>
+                <!--
+                 The next 3 bytes (24 bits) contain the byte- and bit-offset,
+                 were the last byte contains the bit-offset in the last 3 bits
+                 and the byteOffset is encoded in the higher level 21 bits
+                -->
+                <xs:element name="byteOffset" type="xs:unsignedInt"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="21"/>
+                <xs:element name="bitOffset" type="xs:unsignedInt"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="3"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7ResponseParameterWriteVar">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="numItems" type="s7f:byte"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <!--
+
+        Payloads.
+
+    -->
+
+    <xs:element name="S7GeneralPayloadSetupCommunication" type="xs:byte" dfdl:lengthKind="explicit" dfdl:length="0"/>
+
+    <xs:element name="S7RequestPayloadCpuServices">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="transportSize" type="s7f:byte"/><!-- fixed="9"-->
+                <xs:element name="length" type="s7f:byte"/>
+                <xs:element name="sslId" type="s7f:short"/>
+                <xs:element name="sslIndex" type="s7f:short"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7ResponsePayloadCpuServices">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="returnCode" type="s7f:byte"/>
+                <!-- Transport Size: Octet String = 0x09 -> 9 -->
+                <xs:element name="transportSize" type="s7f:byte"/><!-- fixed="9"-->
+                <xs:element name="length" type="s7f:short"/>
+                <xs:element name="sslId" type="s7f:short"/>
+                <xs:element name="sslIndex" type="s7f:short"/>
+                <xs:element name="partialList" minOccurs="0"
+                            dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../length - 4}"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{../length gt 4}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="partialListLengthInWords" type="s7f:short"/>
+                            <xs:element name="partialListCount" type="s7f:short"/>
+                            <xs:element name="sslDataRecords">
+                                <xs:complexType>
+                                    <xs:sequence dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes"
+                                                 dfdl:length="{../length - 8}">
+                                        <xs:choice>
+                                            <xs:element
+                                                ref="s7f:S7ResponsePayloadCpuServicesSslDataRecordModuleIdentification"/>
+                                        </xs:choice>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7ResponsePayloadCpuServicesSslDataRecordModuleIdentification">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="index" type="s7f:short"/>
+                <xs:element name="articleNumber" type="xs:unsignedByte"
+                            dfdl:lengthUnits="bytes" dfdl:length="20" dfdl:lengthKind="explicit"/>
+                <xs:element name="bgType" type="s7f:short"/>
+                <xs:element name="moduleOrOsVersion" type="s7f:short"/>
+                <xs:element name="pgDescriptionFileVersion" type="s7f:short"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7RequestPayloadReadVar" type="xs:byte" dfdl:lengthKind="explicit" dfdl:length="0"/>
+
+    <xs:element name="S7ResponsePayloadReadVar">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- The number of items which should be read is transmitted in the matching parameter -->
+                <xs:element name="numItems" type="s7f:byte"
+                            dfdl:inputValueCalc="{
+                                ../../../../parameters[1]/parameter[dfdl:occursIndex()]/s7f:S7ResponseParameterReadVar/numItems
+                            }"/>
+                <xs:element name="item" minOccurs="0"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{../numItems}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="returnCode" type="s7f:byte"/>
+                            <xs:element name="transportSize" type="s7f:byte"/>
+                            <xs:element name="rawLength" type="s7f:short"/>
+                            <!--
+                                For some reason the types BIT, BYTE_WORD_DWORD and INTEGER are transferred in "bits",
+                                the rest is transferred in "bytes"
+                            -->
+                            <xs:element name="lengthInBytes" type="s7f:short" dfdl:inputValueCalc="{
+                                    if((../transportSize eq 3) or (../transportSize eq 4) or (../transportSize eq 5))
+                                            then fn:ceiling(../rawLength div 8)
+                                            else ../rawLength}"/>
+                            <xs:element name="data" type="xs:hexBinary"
+                                        dfdl:byteOrder="bigEndian" dfdl:lengthUnits="bytes" dfdl:lengthKind="explicit"
+                                        dfdl:length="{../lengthInBytes}"/>
+                            <!--
+                                Transport sizes: BIT, BYTE_WORD_DWORD and OCTET_STRING require a blank byte.
+                                However only if this is not the last item in the result.
+                            -->
+                            <xs:element name="reserved" type="s7f:byte" minOccurs="0"
+                                        dfdl:occursCountKind="expression" dfdl:occursCount="{
+                                            if(((../transportSize eq 3) or
+                                                (../transportSize eq 4) or
+                                                (../transportSize eq 9)) and
+                                                (dfdl:occursIndex() ne ../../numItems)) then 1 else 0}"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7RequestPayloadWriteVar">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- The number of items which should be read is transmitted in the matching parameter -->
+                <xs:element name="numItems" type="s7f:byte"
+                            dfdl:inputValueCalc="{
+                                ../../../../parameters[1]/parameter[dfdl:occursIndex()]/s7f:S7RequestParameterWriteVar/numItems
+                            }"/>
+                <xs:element name="item" minOccurs="0"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{../numItems}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="returnCode" type="s7f:byte"/>
+                            <xs:element name="transportSize" type="s7f:byte"/>
+                            <xs:element name="rawLength" type="s7f:short"/>
+                            <!--
+                                For some reason the types BIT, BYTE_WORD_DWORD and INTEGER are transferred in "bits",
+                                the rest is transferred in "bytes"
+                            -->
+                            <xs:element name="lengthInBytes" type="s7f:short" dfdl:inputValueCalc="{
+                                    if((../transportSize eq 3) or (../transportSize eq 4) or (../transportSize eq 5))
+                                            then fn:ceiling(../rawLength div 8)
+                                            else ../rawLength}"/>
+                            <xs:element name="data" type="xs:hexBinary"
+                                        dfdl:byteOrder="bigEndian" dfdl:lengthUnits="bytes" dfdl:lengthKind="explicit"
+                                        dfdl:length="{../lengthInBytes}"/>
+                            <!--
+                                Transport sizes: BIT, BYTE_WORD_DWORD and OCTET_STRING require a blank byte.
+                                However only if this is not the last item in the result.
+
+                                Actually the S7 device will never process data that contains more
+                                than one item in a write request, so this is rather a cosmetic fine-tuning.
+                            -->
+                            <xs:element name="reserved" type="s7f:byte" minOccurs="0"
+                                        dfdl:occursCountKind="expression" dfdl:occursCount="{
+                                            if(((../transportSize eq 3) or
+                                                (../transportSize eq 4) or
+                                                (../transportSize eq 9)) and
+                                                (dfdl:occursIndex() ne ../../numItems)) then 1 else 0}"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="S7ResponsePayloadWriteVar">
+        <xs:complexType>
+            <xs:sequence>
+                <!-- The number of items which should be read is transmitted in the matching parameter -->
+                <xs:element name="numItems" type="s7f:byte"
+                            dfdl:inputValueCalc="{
+                                ../../../../parameters[1]/parameter[dfdl:occursIndex()]/s7f:S7ResponseParameterWriteVar/numItems
+                            }"/>
+                <xs:element name="item" minOccurs="0"
+                            dfdl:occursCountKind="expression" dfdl:occursCount="{../numItems}">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="returnCode" type="s7f:byte"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
\ No newline at end of file
diff --git a/protocols/src/main/java/.keepMe b/protocols/src/main/java/.keepMe
index cf84b4e..97c6314 100644
--- a/protocols/src/main/java/.keepMe
+++ b/protocols/src/main/java/.keepMe
@@ -14,3 +14,7 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 
+This file is required to force the existence of the src/main/java directory
+which activates the "java-module" maven profile.
+
+PLEASE DO NOT DELETE ... it will break the build.
\ No newline at end of file
diff --git a/protocols/src/test/java/org/apache/plc4x/protocols/S7FullStackProtocolTest.java b/protocols/src/test/java/org/apache/plc4x/protocols/S7FullStackProtocolTest.java
new file mode 100644
index 0000000..ddee1e7
--- /dev/null
+++ b/protocols/src/test/java/org/apache/plc4x/protocols/S7FullStackProtocolTest.java
@@ -0,0 +1,31 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.protocols;
+
+/**
+ * Executes all tests for the ISO on TCP / TPKT protocol.
+ */
+public class S7FullStackProtocolTest extends AbstractProtocolTest {
+
+    public S7FullStackProtocolTest() {
+        super("org/apache/plc4x/protocols/s7-full-stack-protocol.tdml");
+    }
+
+}
diff --git a/protocols/src/test/resources/org/apache/plc4x/protocols/s7-full-stack-protocol.tdml b/protocols/src/test/resources/org/apache/plc4x/protocols/s7-full-stack-protocol.tdml
new file mode 100644
index 0000000..752d57c
--- /dev/null
+++ b/protocols/src/test/resources/org/apache/plc4x/protocols/s7-full-stack-protocol.tdml
@@ -0,0 +1,704 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+
+<testSuite xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+           xmlns:test="plc4x-protocol-test"
+           xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+           xmlns:s7="http://plc4x.apache.org/s7-full"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           suiteName="S7 protocol (Full-Stack KPKT + COTP + S7)"
+           description="Testsuite for the full stack of the S7 protocol"
+           defaultRoundTrip="true">
+
+    <tdml:defineSchema name="s7Schema" elementFormDefault="unqualified">
+        <!-- Import the Schema -->
+        <xs:import namespace="http://plc4x.apache.org/s7-full"
+                   schemaLocation="s7-full-stack-protocol.dfdl.xsd"/>
+
+        <!-- Import the format settings -->
+        <dfdl:format ref="s7:s7FullFormat"/>
+
+        <!-- Define the root element name and type -->
+        <xs:element name="tpktMessage" type="s7:TpktMessageType"/>
+    </tdml:defineSchema>
+
+    <!--
+        In this test-case the data should be parsable to a valid result.
+        It's a TPKT package containing a COTP connection-response payload.
+    -->
+    <tdml:parserTestCase name="TPKT: tpktPacketContainingCotpConnectResponse"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Simple TKPT packet which contains a COTP Connection-Response as payload.">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300001211D00001000200C00109C1020100C2020102</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <!-- Referencing what we defined as root element in the defineSchema section -->
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>18</length>
+                    <userData>
+                        <headerLength>17</headerLength>
+                        <type>208</type>
+                        <CotpTpduConnectionResponse>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>192</type>
+                                    <parameterLength>1</parameterLength>
+                                    <CotpParameterTpduSize>
+                                        <tpduSize>9</tpduSize>
+                                    </CotpParameterTpduSize>
+                                </parameter>
+                                <parameter>
+                                    <type>193</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCallingTsap>
+                                        <tsapId>256</tsapId>
+                                    </CotpParameterCallingTsap>
+                                </parameter>
+                                <parameter>
+                                    <type>194</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCalledTsap>
+                                        <tsapId>258</tsapId>
+                                    </CotpParameterCalledTsap>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionResponse>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <!--
+        In this test-case the packet doesn't start with the required magic byte 0x03.
+    -->
+    <tdml:parserTestCase name="TPKT: invalidMagicByte"
+                         root="tpktMessage"
+                         model="s7Schema">
+        <tdml:document>
+            <tdml:documentPart type="byte">0400001611D00001000200C00109C1020100C2020102</tdml:documentPart>
+        </tdml:document>
+
+        <tdml:errors>
+            <tdml:error>Parse Error</tdml:error>
+        </tdml:errors>
+    </tdml:parserTestCase>
+
+    <!--
+        In this test-case the payload of the packet doesn't match the
+        length provided in the packet header (Too short)
+    -->
+    <tdml:parserTestCase name="TPKT: tooShortPayload"
+                         root="tpktMessage"
+                         model="s7Schema">
+        <tdml:document>
+            <tdml:documentPart type="byte">0300001611D00001000200C00109C102010</tdml:documentPart>
+        </tdml:document>
+
+        <tdml:errors>
+            <tdml:error>Parse Error</tdml:error>
+        </tdml:errors>
+    </tdml:parserTestCase>
+
+    <!--
+        In this test-case the payload of the packet doesn't match the
+        length provided in the packet header (Too long)
+    -->
+    <tdml:parserTestCase name="TPKT: tooLongPayload"
+                         root="tpktMessage"
+                         model="s7Schema">
+        ยด
+        <tdml:document>
+            <tdml:documentPart type="byte">0300001611D00001000200C00109C1020100C20201021234567890</tdml:documentPart>
+        </tdml:document>
+
+        <tdml:errors>
+            <tdml:error>Parse Error</tdml:error>
+        </tdml:errors>
+    </tdml:parserTestCase>
+
+    <!--
+
+        Tests for the basic TPDU types (no parameters)
+
+    -->
+
+    <tdml:parserTestCase name="COTP: typeConnectionRequest"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Connection Request TPDU">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000706E00001000200</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>7</length>
+                    <userData>
+                        <headerLength>6</headerLength>
+                        <type>224</type>
+                        <CotpTpduConnectionRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                        </CotpTpduConnectionRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: typeConnectionResponse"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Connection Response TPDU">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000706D00001000200</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>7</length>
+                    <userData>
+                        <headerLength>6</headerLength>
+                        <type>208</type>
+                        <CotpTpduConnectionResponse>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                        </CotpTpduConnectionResponse>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: typeDisconnectionRequest"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Disconnection Request TPDU">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000706800001000200</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>7</length>
+                    <userData>
+                        <headerLength>6</headerLength>
+                        <type>128</type>
+                        <CotpTpduDisconnectRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <disconnectReason>0</disconnectReason>
+                        </CotpTpduDisconnectRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: typeDisconnectionResponse"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Disconnection Response TPDU">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000605C000010002</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>6</length>
+                    <userData>
+                        <headerLength>5</headerLength>
+                        <type>192</type>
+                        <CotpTpduDisconnectResponse>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                        </CotpTpduDisconnectResponse>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: typeError"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Error TPDU">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">030000050470000102</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>5</length>
+                    <userData>
+                        <headerLength>4</headerLength>
+                        <type>112</type>
+                        <CotpTpduError>
+                            <destinationReference>1</destinationReference>
+                            <rejectCause>2</rejectCause>
+                        </CotpTpduError>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: typeData"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Data TPDU">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000302F002</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>3</length>
+                    <userData>
+                        <headerLength>2</headerLength>
+                        <type>240</type>
+                        <CotpTpduData>
+                            <endOfTransmission>0</endOfTransmission>
+                            <tpduRef>2</tpduRef>
+                        </CotpTpduData>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: typeDataEndOfTransmission"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Data (End Of Transmission) TPDU">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000302F082</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>3</length>
+                    <userData>
+                        <headerLength>2</headerLength>
+                        <type>240</type>
+                        <CotpTpduData>
+                            <endOfTransmission>1</endOfTransmission>
+                            <tpduRef>2</tpduRef>
+                        </CotpTpduData>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <!--
+
+        Tests for the parameter types.
+
+    -->
+
+    <tdml:parserTestCase name="COTP: parameterTpduSize"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="parameterTpduSize">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000A09E00001000200C00109</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>10</length>
+                    <userData>
+                        <headerLength>9</headerLength>
+                        <type>224</type>
+                        <CotpTpduConnectionRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>192</type>
+                                    <parameterLength>1</parameterLength>
+                                    <CotpParameterTpduSize>
+                                        <tpduSize>9</tpduSize>
+                                    </CotpParameterTpduSize>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: parameterCallingTsap"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="parameterCallingTsap">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000B0AE00001000200C1020009</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>11</length>
+                    <userData>
+                        <headerLength>10</headerLength>
+                        <type>224</type>
+                        <CotpTpduConnectionRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>193</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCallingTsap>
+                                        <tsapId>9</tsapId>
+                                    </CotpParameterCallingTsap>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: parameterCalledTsap"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="parameterCalledTsap">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000B0AE00001000200C2020009</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>11</length>
+                    <userData>
+                        <headerLength>10</headerLength>
+                        <type>224</type>
+                        <CotpTpduConnectionRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>194</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCalledTsap>
+                                        <tsapId>9</tsapId>
+                                    </CotpParameterCalledTsap>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: parameterChecksum"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="parameterChecksum">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000A09E00001000200C30109</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>10</length>
+                    <userData>
+                        <headerLength>9</headerLength>
+                        <type>224</type>
+                        <CotpTpduConnectionRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>195</type>
+                                    <parameterLength>1</parameterLength>
+                                    <CotpParameterChecksum>
+                                        <checksum>9</checksum>
+                                    </CotpParameterChecksum>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: parameterDisconnectAdditionalInformation"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="parameterDisconnectAdditionalInformation">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300000F0EE00001000200E006010203040506</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>15</length>
+                    <userData>
+                        <headerLength>14</headerLength>
+                        <type>224</type>
+                        <CotpTpduConnectionRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>224</type>
+                                    <parameterLength>6</parameterLength>
+                                    <CotpParameterDisconnectAdditionalInformation>
+                                        <data>010203040506</data>
+                                    </CotpParameterDisconnectAdditionalInformation>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <!--
+
+        Tests for typical packets used in PLC4X
+
+    -->
+
+    <tdml:parserTestCase name="COTP: scenarioConnectionRequest"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="COTP Connection request used for initiating an S7 protocol connection.">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300001211E00001000200C1020100C2020102c0010a</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>18</length>
+                    <userData>
+                        <headerLength>17</headerLength>
+                        <type>224</type>
+                        <CotpTpduConnectionRequest>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>193</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCallingTsap>
+                                        <tsapId>256</tsapId>
+                                    </CotpParameterCallingTsap>
+                                </parameter>
+                                <parameter>
+                                    <type>194</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCalledTsap>
+                                        <tsapId>258</tsapId>
+                                    </CotpParameterCalledTsap>
+                                </parameter>
+                                <parameter>
+                                    <type>192</type>
+                                    <parameterLength>1</parameterLength>
+                                    <CotpParameterTpduSize>
+                                        <tpduSize>10</tpduSize>
+                                    </CotpParameterTpduSize>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionRequest>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <tdml:parserTestCase name="COTP: scenarioConnectionResponse"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Minimal valid COTP Message">
+        <!-- Define the input -->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300001211D00001000200C00109C1020100C2020102</tdml:documentPart>
+        </tdml:document>
+
+        <!-- Define the expected output -->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>18</length>
+                    <userData>
+                        <headerLength>17</headerLength>
+                        <type>208</type>
+                        <CotpTpduConnectionResponse>
+                            <destinationReference>1</destinationReference>
+                            <sourceReference>2</sourceReference>
+                            <protocolClass>0</protocolClass>
+                            <parameters>
+                                <parameter>
+                                    <type>192</type>
+                                    <parameterLength>1</parameterLength>
+                                    <CotpParameterTpduSize>
+                                        <tpduSize>9</tpduSize>
+                                    </CotpParameterTpduSize>
+                                </parameter>
+                                <parameter>
+                                    <type>193</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCallingTsap>
+                                        <tsapId>256</tsapId>
+                                    </CotpParameterCallingTsap>
+                                </parameter>
+                                <parameter>
+                                    <type>194</type>
+                                    <parameterLength>2</parameterLength>
+                                    <CotpParameterCalledTsap>
+                                        <tsapId>258</tsapId>
+                                    </CotpParameterCalledTsap>
+                                </parameter>
+                            </parameters>
+                        </CotpTpduConnectionResponse>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase>
+
+    <!--tdml:parserTestCase name="COTP: scenarioDataTpdu"
+                         root="tpktMessage"
+                         model="s7Schema"
+                         description="Typical Data TPDU used for transferring S7 packets.">
+        <!- Define the input ->
+        <tdml:document>
+            <tdml:documentPart type="byte">0300001f02f080320100000001000e00000401120a10010001000082000004</tdml:documentPart>
+        </tdml:document>
+
+        <!- Define the expected output ->
+        <tdml:infoset>
+            <tdml:dfdlInfoset>
+                <test:tpktMessage>
+                    <magicByte>3</magicByte>
+                    <reserved>0</reserved>
+                    <length>29</length>
+                    <userData>
+                        <headerLength>2</headerLength>
+                        <type>240</type>
+                        <CotpTpduData>
+                            <endOfTransmission>1</endOfTransmission>
+                            <tpduRef>0</tpduRef>
+                        </CotpTpduData>
+                    </userData>
+                </test:tpktMessage>
+            </tdml:dfdlInfoset>
+        </tdml:infoset>
+    </tdml:parserTestCase-->
+
+</testSuite>
+
+