diff --git a/L2TP_CNL113603.tpd b/L2TP_CNL113603.tpd
new file mode 100644
index 0000000000000000000000000000000000000000..8df361133db3b3817e0078b632a63f88df8f5566
--- /dev/null
+++ b/L2TP_CNL113603.tpd
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Ericsson
+
+  All rights reserved. This program and the accompanying materials
+  are made available under the terms of the Eclipse Public License v1.0
+  which accompanies this distribution, and is available at
+  http://www.eclipse.org/legal/epl-v10.html
+
+
+   File:               L2TP_CNL113603.tpd
+   Description:        tpd project file
+   Rev:                R2A
+   Prodnr:             CNL 113 603
+
+ -->
+<TITAN_Project_File_Information version="1.0">
+  <ProjectName>L2TP_CNL113603</ProjectName>
+  <ReferencedProjects>
+    <ReferencedProject name="ProtocolModules_Common" projectLocationURI="../COMMON/ProtocolModules_Common.tpd"/>
+  </ReferencedProjects>
+  <Folders>
+    <FolderResource projectRelativePath="src" relativeURI="src"/>
+  </Folders>
+  <Files>
+    <FileResource projectRelativePath="src/L2TP_EncDec.cc" relativeURI="src/L2TP_EncDec.cc"/>
+    <FileResource projectRelativePath="src/L2TP_Types.ttcn" relativeURI="src/L2TP_Types.ttcn"/>
+  </Files>
+  <ActiveConfiguration>Default</ActiveConfiguration>
+  <Configurations>
+    <Configuration name="Default">
+      <ProjectProperties>
+        <MakefileSettings>
+          <generateInternalMakefile>true</generateInternalMakefile>
+          <GNUMake>true</GNUMake>
+          <incrementalDependencyRefresh>true</incrementalDependencyRefresh>
+          <targetExecutable>bin/L2TP_CNL113603</targetExecutable>
+        </MakefileSettings>
+        <LocalBuildSettings>
+          <workingDirectory>bin</workingDirectory>
+        </LocalBuildSettings>
+        <NamingCoventions>
+          <enableProjectSpecificSettings>true</enableProjectSpecificSettings>
+          <function>.*</function>
+          <externalFunction>.*</externalFunction>
+          <moduleParameter>.*</moduleParameter>
+          <formalParameter>.*</formalParameter>
+        </NamingCoventions>
+      </ProjectProperties>
+    </Configuration>
+  </Configurations>
+</TITAN_Project_File_Information>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1862125dbbe2a2817aaab5874b65e8c13367c777
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# titan.ProtocolModules.L2TP
+
+Main project page:
+
+https://projects.eclipse.org/projects/tools.titan
+
+The source code of the TTCN-3 compiler and executor:
+
+https://github.com/eclipse/titan.core
diff --git a/doc/L2TP_CNL113603_FS.doc b/doc/L2TP_CNL113603_FS.doc
new file mode 100644
index 0000000000000000000000000000000000000000..8c2818428ed4c744a3112fb4f5e294ded4212706
Binary files /dev/null and b/doc/L2TP_CNL113603_FS.doc differ
diff --git a/doc/L2TP_CNL113603_PRI.doc b/doc/L2TP_CNL113603_PRI.doc
new file mode 100644
index 0000000000000000000000000000000000000000..9830fd029cdc69a2a45feec154ff4792d081b431
Binary files /dev/null and b/doc/L2TP_CNL113603_PRI.doc differ
diff --git a/doc/L2TP_CNL113603_UG.doc b/doc/L2TP_CNL113603_UG.doc
new file mode 100644
index 0000000000000000000000000000000000000000..686c254b8eadb7e0a0d3689c72ac2daea47b8025
Binary files /dev/null and b/doc/L2TP_CNL113603_UG.doc differ
diff --git a/src/L2TP_EncDec.cc b/src/L2TP_EncDec.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3f2c90b2b1e4a079c87d7db18ca50e52001b69b8
--- /dev/null
+++ b/src/L2TP_EncDec.cc
@@ -0,0 +1,312 @@
+/******************************************************************************
+* Copyright (c) 2008, 2015  Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Endre Kulcsar
+* Gabor Szalai
+******************************************************************************/
+//
+//  File:     L2TP_EncDec.cc
+//  Rev:      R2A
+//  Prodnr:   CNL 113 603
+//  Reference: RFC 2661
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "L2TP_Types.hh"
+
+#include <openssl/md5.h>
+#include <time.h>
+ 
+namespace L2TP__Types {
+
+#define CTRL_MSG_HDR_LENGTH 20
+// Length of L2TP control message header (Length,Nr and Ns fields are mandatory) + Length of Message Type AVP
+
+
+// calculates 16 bit MD5 message digest
+unsigned char * calc_MD5(OCTETSTRING& pl_input, int pl_size, unsigned char * output)
+   {     
+      MD5(pl_input,(size_t) pl_size,output);
+      return output;   
+   }
+
+OCTETSTRING enc__PDU__L2TP(const PDU__L2TP& pdu)
+{
+    if (TTCN_Logger::log_this_event(TTCN_DEBUG)) {
+	TTCN_Logger::begin_event(TTCN_DEBUG);
+	TTCN_Logger::log_event("Encoding PDU_L2TP: ");
+	pdu.log();
+	TTCN_Logger::end_event();
+    }
+
+    TTCN_Buffer buf;
+    pdu.encode(PDU__L2TP_descr_, buf, TTCN_EncDec::CT_RAW);
+    
+    // ret_val is the RAW encoded PDU without any AVP Hiding
+    // if there are no H_BITs equal to 1 this will be returned from enc__PDU__L2TP             
+    OCTETSTRING ret_val(buf.get_len(), buf.get_data());
+                 
+    // only control msgs use hiding (tBit = 1)
+    const unsigned char *T_BIT = pdu.header().tBit();
+    if (*T_BIT  && (ret_val.lengthof() >= CTRL_MSG_HDR_LENGTH))  // if ctrl message and not ZLB    
+      {          
+        OCTETSTRING ret_val_ctrl_msg = substr(ret_val,0,CTRL_MSG_HDR_LENGTH); // copy original msg header
+           
+        const unsigned char * avp_length;
+        unsigned int avp_length_int;
+        const unsigned char * avp_type;
+        //unsigned int avp_type_int;
+        unsigned int index = CTRL_MSG_HDR_LENGTH; 
+        //unsigned int index_rv = CTRL_MSG_HDR_LENGTH; 
+        bool H_BIT;       
+        OCTETSTRING AVP_TYPE;
+        OCTETSTRING AVP_HEADER;
+        OCTETSTRING AVP_VALUE; 
+        OCTETSTRING AVP_LENGTH;                               
+        const unsigned char header_mask[2] = {0xfc, 0x00};
+        unsigned char avp_hidden_length[2];       
+        srand((unsigned)time(0)); 
+
+        while (index < buf.get_len() )
+          { 
+            avp_length = ((const unsigned char *)ret_val) + index;                                             
+            H_BIT = ((avp_length[0] & 0x40) >> 6); // H_BIT = 1 -> hiding is needed for this AVP                              
+            avp_length_int = ((avp_length[0] & 0x03) << 8) + avp_length[1]; // length of AVP
+            AVP_LENGTH = int2oct(avp_length_int-6,2);                       
+            AVP_HEADER = substr(ret_val,index,6);                 
+            avp_type = ((const unsigned char *)ret_val)+ index+4;
+            AVP_TYPE = OCTETSTRING(2,avp_type);
+            AVP_VALUE = substr(ret_val,index+6,avp_length_int-6);  
+            OCTETSTRING AVP_VALUE_HIDDEN(0,NULL);                                 
+            //avp_type_int = (avp_type[0] << 8) + avp_type[1];
+            unsigned int index_rv = CTRL_MSG_HDR_LENGTH;
+                                      
+            if (H_BIT == TRUE)   // hidden AVP is needed
+              {                             
+                bool bound_flag = FALSE;                                                    
+                OCTETSTRING random_vector;
+                
+                // find random vector "most closely preceding"
+                while (index_rv < index )
+                 { 
+                   const unsigned char *avp_length_find_rv = ((const unsigned char *)ret_val)+index_rv;
+                   unsigned int avp_length_int_find_rv = ((avp_length_find_rv[0] & 0x03) << 8) + avp_length_find_rv[1]; // length of AVP 
+                           
+                   const unsigned char *avp_type_find_rv = ((const unsigned char *)ret_val) + index_rv+4;
+                   unsigned int avp_type_int_find_rv = (avp_type_find_rv[0] << 8) + avp_type_find_rv[1];
+                                                       
+                   if (avp_type_int_find_rv == 36)  // if AVP's Attr type is rand vect   
+                     {
+                       random_vector = substr(ret_val,index_rv+6,avp_length_int_find_rv-6);
+                       bound_flag = TRUE;                
+                     } 
+                       
+                   index_rv = index_rv + avp_length_int_find_rv; // points to start of next AVP in original stream
+                 } 
+                                          
+                if (bound_flag == FALSE)    // random_vector.is_bound() == NULL 
+                   {TTCN_error("%s","No Random Vector AVP present");}  // Error: No Random Vector AVP before Hidden AVP!                      
+                                           
+                // Calculate RANDOM_PADDING needed for HIDDEN_AVP_SUBFORMAT
+                int random = rand();  
+                OCTETSTRING HIDDEN_AVP_SUBFORMAT;               
+                if ( (random % (tsp__Max__Random__Padding__Length+1)) == 0 )
+                  {   
+                    HIDDEN_AVP_SUBFORMAT = AVP_LENGTH + AVP_VALUE;  
+                  }
+                else   
+                  {            
+                    OCTETSTRING RANDOM_PADDING(int2oct(0,random % (tsp__Max__Random__Padding__Length+1)));                            
+                    HIDDEN_AVP_SUBFORMAT = AVP_LENGTH + AVP_VALUE + RANDOM_PADDING;
+                  }  
+                            
+                // AVP padded to exact multiple of 16   
+                int avp_padding_length = 16 -(HIDDEN_AVP_SUBFORMAT.lengthof() % 16 );
+                unsigned char padding[avp_padding_length];
+                for(int i = 0; i < avp_padding_length; i++) 
+                  {padding[i] = 0x00;}                         
+                OCTETSTRING AVP_PADDING = OCTETSTRING(avp_padding_length,padding);                                                               
+                OCTETSTRING AVP_VALUE_PADDED = HIDDEN_AVP_SUBFORMAT + AVP_PADDING;  
+                                                  
+                // CONCATENATION is input into HIDE procedure                                                                
+                OCTETSTRING CONCATENATION =  AVP_TYPE + tsp__L2TP__SharedSecret + random_vector;
+                     
+                // HIDE PROCEDURE
+                 OCTETSTRING b;
+                 OCTETSTRING c;  
+                 unsigned char MD5_value[16];                            
+                 for (int j = 0; j < (AVP_VALUE_PADDED.lengthof()) ; j=j+16) 
+                   {      
+                     b = OCTETSTRING(16,(const unsigned char *)calc_MD5(CONCATENATION,CONCATENATION.lengthof(),MD5_value));                              
+                     c = ((substr(AVP_VALUE_PADDED,j ,16 )) ^ b);                                                          
+                     CONCATENATION = tsp__L2TP__SharedSecret + c;                              
+                     AVP_VALUE_HIDDEN = AVP_VALUE_HIDDEN + c;      
+                   } 
+                                                        
+                 // modify length field in AVP_HEADER to actual length of hidden AVP               
+                 unsigned int avp_hidden_length_int = 6 + AVP_VALUE_HIDDEN.lengthof();           
+                 avp_hidden_length[0] = (avp_hidden_length_int & 0x0300)>> 8; 
+                 avp_hidden_length[1] = (avp_hidden_length_int & 0xff);  
+                 unsigned char* avp_header2 = (unsigned char*)(const unsigned char*)AVP_HEADER; 
+                 avp_header2[0] &= header_mask[0];
+                 avp_header2[1] &= header_mask[1];              
+                 avp_header2[0] |= avp_hidden_length[0];
+                 avp_header2[1] |= avp_hidden_length[1]; 
+                           
+                 ret_val_ctrl_msg = ret_val_ctrl_msg  + AVP_HEADER + AVP_VALUE_HIDDEN;  // Add new hidden AVP                                                                                    
+               }
+             else  // original (not hidden) AVP is used because for this AVP H_BIT == FALSE
+               {
+                 ret_val_ctrl_msg = ret_val_ctrl_msg + substr(ret_val,index,avp_length_int);                 
+               }              
+                index = index + avp_length_int; // points to start of next AVP in original stream
+           } // end of while (index < buf.get_len() )
+                       
+          ret_val = ret_val_ctrl_msg;     
+        }  // end of  if (*T_BIT)
+          
+   //fill in true length of complete PDU if lengthValue field is present
+   if (pdu.header().lengthValue().ispresent())
+    {           
+      unsigned int PDU_SIZE_INT = ret_val.lengthof();
+      unsigned char PDU_SIZE_CHAR[2]; 
+      PDU_SIZE_CHAR[0] = (PDU_SIZE_INT & 0xff00) >> 8;
+      PDU_SIZE_CHAR[1] = (PDU_SIZE_INT & 0xff );
+     
+      OCTETSTRING PDU_SIZE_OCTETSTRING(2, PDU_SIZE_CHAR);
+      
+      ret_val = substr(ret_val,0,2) + PDU_SIZE_OCTETSTRING + substr(ret_val,4,PDU_SIZE_INT-4);   
+    } 
+        
+    if (TTCN_Logger::log_this_event(TTCN_DEBUG)) {
+	TTCN_Logger::begin_event(TTCN_DEBUG);
+	TTCN_Logger::log_event("Encoded PDU_L2TP: ");
+	ret_val.log();
+	TTCN_Logger::end_event();
+    }    
+    return ret_val;
+}
+
+PDU__L2TP dec__PDU__L2TP(const OCTETSTRING& stream)
+{
+    if (TTCN_Logger::log_this_event(TTCN_DEBUG)) {
+	TTCN_Logger::begin_event(TTCN_DEBUG);
+	TTCN_Logger::log_event("Decoding PDU_L2TP: ");
+	stream.log();
+	TTCN_Logger::end_event();
+    }
+      TTCN_Buffer buf;   
+
+    // if control message check AVPs whether hiding was used
+    if  ((((((const unsigned char *)stream)[0]) & 0x80) == 0x80)  && (stream.lengthof() >= CTRL_MSG_HDR_LENGTH))   // if control message and not ZLB
+      {      
+       OCTETSTRING stream_ctrl_msg = substr(stream,0,CTRL_MSG_HDR_LENGTH); // copy original msg header              
+       unsigned int index = CTRL_MSG_HDR_LENGTH; 
+       //unsigned int index_rv = CTRL_MSG_HDR_LENGTH; 
+       const unsigned char * avp_length;       
+       unsigned avp_length_int;
+       //unsigned avp_length_int_orig;      
+       bool H_BIT;    
+       while (index < (unsigned int)stream.lengthof() )
+         {  
+           avp_length = ((const unsigned char *)stream) + index;  
+           H_BIT = ((avp_length[0] & 0x40) >> 6); //if H_BIT = 1 -> hiding was used for this AVP          
+           avp_length_int = ((avp_length[0] & 0x03) << 8) + avp_length[1]; // length of AVP 
+           //avp_length_int_orig = avp_length_int;
+           OCTETSTRING AVP_HEADER = substr(stream,index,6); 
+           const unsigned char header_mask[2] = {0xfc, 0x00};
+           unsigned char* avp_hidden_length;    //[2];
+           unsigned int index_rv = CTRL_MSG_HDR_LENGTH;           
+                                           
+           if (H_BIT == TRUE)  //  hiding was used for this AVP
+             {                                
+              bool bound_flag = FALSE;                                                    
+              OCTETSTRING random_vector;
+                
+              // find random vector "most closely preceding"  
+              OCTETSTRING HIDDEN_AVP_SUBFORMAT(0,NULL); 
+              while (index_rv < index )
+                { 
+                  const unsigned char *avp_length_find_rv = ((const unsigned char *)stream)+index_rv;
+                  unsigned int avp_length_int_find_rv = ((avp_length_find_rv[0] & 0x03) << 8) + avp_length_find_rv[1]; // length of AVP   
+                                  
+                  const unsigned char *avp_type_find_rv = ((const unsigned char *)stream) + index_rv+4;
+                  unsigned int avp_type_int_find_rv = (avp_type_find_rv[0] << 8) + avp_type_find_rv[1];
+                                                                                                
+                  if (avp_type_int_find_rv == 36)  // if AVP's Attr type is rand vect   
+                    {
+                      random_vector = substr(stream,index_rv+6,avp_length_int_find_rv-6);   
+                      bound_flag = TRUE;                
+                    }                                                                              
+                   index_rv = index_rv + avp_length_int_find_rv; // points to start of next AVP in original stream                  
+                 }                  
+               if (bound_flag == FALSE)    
+                  {TTCN_error("%s","No Random Vector AVP present");}  // Error: No Random Vector AVP before Hidden AVP! 
+ 
+               // CONCATENATION is input into HIDE procedure                                                                
+               OCTETSTRING CONCATENATION;                                 
+               const unsigned char *avp_type = ((const unsigned char *)stream) + index+4; //type of AVP                
+               OCTETSTRING AVP_TYPE = OCTETSTRING(2,avp_type);
+               unsigned char MD5_value[16];                 
+               OCTETSTRING b;
+               OCTETSTRING p;                                                                            
+               unsigned int j = index + avp_length_int-32;
+                                            
+               while(j >= (index + 6))  
+                {                                                                                                                  
+                  CONCATENATION = tsp__L2TP__SharedSecret + substr(stream,j,16);                                                                                                                               
+                  b = OCTETSTRING(16,(const unsigned char *)calc_MD5(CONCATENATION,CONCATENATION.lengthof(),MD5_value));                                                                                     
+                  p = b ^ substr(stream,j + 16,16);                                                   
+                  HIDDEN_AVP_SUBFORMAT = p + HIDDEN_AVP_SUBFORMAT;                              
+                  j = j-16;         
+                }                     
+                   CONCATENATION = AVP_TYPE + tsp__L2TP__SharedSecret + random_vector;                   
+                   b = OCTETSTRING(16,(const unsigned char *)calc_MD5(CONCATENATION,CONCATENATION.lengthof(),MD5_value));                          
+                   p = b ^ substr(stream,index + 6,16); 
+                   HIDDEN_AVP_SUBFORMAT = p + HIDDEN_AVP_SUBFORMAT;  
+                                                                                                                      
+                 // modify length field in AVP_HEADER to actual length of hidden AVP                              
+                 avp_hidden_length = (unsigned char*)(const unsigned char*)HIDDEN_AVP_SUBFORMAT;
+                 unsigned int avp_length_int_unhidden = 6 + (((avp_hidden_length[0] & 0x03) << 8) + avp_hidden_length[1]); // complete length of AVP  
+                 unsigned int avp_length_int_unhidden_copy = avp_length_int_unhidden;                                
+                 unsigned char* avp_header2 = (unsigned char*)(const unsigned char*)AVP_HEADER;                                     
+                 avp_header2[0] &= header_mask[0];
+                 avp_header2[1] &= header_mask[1];                  
+                 avp_header2[0] |= ((avp_length_int_unhidden & 0x0300)>> 8); 
+                 avp_header2[1] |= (avp_length_int_unhidden & 0xff);  
+                                                                            
+                 stream_ctrl_msg = stream_ctrl_msg + AVP_HEADER + substr(HIDDEN_AVP_SUBFORMAT,2,avp_length_int_unhidden_copy-6);  
+                                                     
+             } // end of if (H_BIT == TRUE)
+           else  // original (not hidden) AVP is used because for this AVP H_BIT == FALSE
+             {
+               stream_ctrl_msg = stream_ctrl_msg + substr(stream,index,avp_length_int);                               
+             }                                                                          
+            index = index + avp_length_int;        
+         } // end of while                    
+          buf.put_os(stream_ctrl_msg); 
+      } // end of  if control message
+      
+    else  // user data message
+      {
+          buf.put_os(stream);      
+      }
+              
+    PDU__L2TP ret_val;
+    ret_val.decode(PDU__L2TP_descr_, buf, TTCN_EncDec::CT_RAW);
+
+    if (TTCN_Logger::log_this_event(TTCN_DEBUG)) {
+	TTCN_Logger::begin_event(TTCN_DEBUG);
+	TTCN_Logger::log_event("Decoded PDU_L2TP: ");
+	ret_val.log();
+	TTCN_Logger::end_event();
+    }    
+    return ret_val;
+  }  // end of function dec__PDU__L2TP
+
+}  // end of module
diff --git a/src/L2TP_Types.ttcn b/src/L2TP_Types.ttcn
new file mode 100644
index 0000000000000000000000000000000000000000..c7773264ccc7d8ad27f7eff0ddc4ac9daa1664a3
--- /dev/null
+++ b/src/L2TP_Types.ttcn
@@ -0,0 +1,812 @@
+/******************************************************************************
+* Copyright (c) 2008, 2015  Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Endre Kulcsar
+* Gabor Szalai
+******************************************************************************/
+//
+//  File:     L2TP_Types.ttcn
+//  Rev:      R2A
+//  Prodnr:   CNL 113 603
+//  Reference: RFC 2661
+//
+///////////////////////////////////////////////////////////////////////////////
+
+module L2TP_Types
+{
+   import from General_Types all;
+   
+   external function enc_PDU_L2TP(in PDU_L2TP pdu) return octetstring
+
+   external function dec_PDU_L2TP(in octetstring stream) return PDU_L2TP
+    
+   modulepar
+   {
+     octetstring tsp_L2TP_SharedSecret := '00000000'O; 
+     //This value is needed for hiding of AVPs
+     
+     Random_Padding_Length tsp_Max_Random_Padding_Length := 10;    
+     // Determines the max number of Random additional octets used to obscure length 
+     // of the Attribute Value that is being hidden. See RFC 2661 section 4.3.
+     // Its value is an integer larger than or equal to 0, (Padding value is all zeros)
+   } 
+   
+   type integer Random_Padding_Length (0..infinity);   
+     
+   type integer INT2_BO_LAST (0..65535) with { variant "FIELDLENGTH(16), COMP(nosign), BYTEORDER(last)" };
+   
+   type record AVP_Header
+   { BIT1            mBit,
+     BIT1            hBit,
+     BIT4            reserved,
+     integer         lengthValue, 
+     INT2_BO_LAST    vendorId,   // 0
+     INT2_BO_LAST    attributeType     
+   } with { 
+            variant (mBit,hBit,reserved,lengthValue) "FIELDORDER(msb)";
+            variant (lengthValue)   "BYTEORDER(last)";
+            variant (lengthValue)   "FIELDLENGTH(10)";     
+          } 
+       
+   // AVPs ==============================================================
+   
+   type record MessageTypeAVP
+   {
+     AVP_Header      aVP_Header,  // type 0
+     INT2_BO_LAST    messageTypeValue     
+   } with {
+            variant "PRESENCE(aVP_Header.attributeType = 0)"; 
+            variant (aVP_Header) "LENGTHTO(aVP_Header,messageTypeValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";
+          }
+
+   type record RandomVectorAVP
+   {
+     AVP_Header     aVP_Header, // type 36
+     octetstring    randomOctetString
+   } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 36)";   
+            variant (aVP_Header) "LENGTHTO(aVP_Header,randomOctetString)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";
+         }
+      
+  type record ResultCodeAVP
+  {
+    AVP_Header      aVP_Header,   // type 1
+    INT2_BO_LAST    resultCode, 
+    INT2_BO_LAST    errorCode     optional,
+    charstring      errorMessage  optional
+  } with {
+           variant "PRESENCE(aVP_Header.attributeType = 1)";    
+           variant (aVP_Header) "LENGTHTO(aVP_Header,resultCode,errorCode,errorMessage)"; 
+           variant (aVP_Header) "LENGTHINDEX(lengthValue)";  
+         } 
+           
+  type record  ProtocolVersionAVP
+  {
+    AVP_Header      aVP_Header,   // type 2
+    INT1            ver,     //1
+    INT1            rev      //0 
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 2)"; 
+            variant (aVP_Header) "LENGTHTO(aVP_Header,ver,rev)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";
+         } 
+         
+  type record  FramingCapabilitiesAVP
+  {
+    AVP_Header      aVP_Header,   // type 3  
+    bitstring       reserved length (30),
+    BIT1            aBit,
+    BIT1            sBit
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 3)";
+            variant (aVP_Header) "LENGTHTO(aVP_Header,reserved,aBit,sBit)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";    
+            variant (reserved) "FIELDLENGTH(30)";      
+            variant (reserved,aBit,sBit) "FIELDORDER(msb)";
+         }
+ 
+  type record BearerCapabilitiesAVP 
+  { 
+    AVP_Header      aVP_Header,   // type 4
+    bitstring       reserved length (30),
+    BIT1            aBit,
+    BIT1            dBit     
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 4)";
+            variant (aVP_Header) "LENGTHTO(aVP_Header,reserved,aBit,dBit)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";     
+            variant (reserved) "FIELDLENGTH(30)";        
+            variant (reserved,aBit,dBit) "FIELDORDER(msb)";  
+         }  
+         
+  type record TieBreakerAVP
+  {
+    AVP_Header      aVP_Header,   // type 5  
+    OCT8            tIEBreakValue             
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 5)";   
+            variant (aVP_Header) "LENGTHTO(aVP_Header,tIEBreakValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         } 
+         
+  type record FirmwareRevisionAVP
+  {
+    AVP_Header      aVP_Header, // type 6   
+    INT2_BO_LAST    firmwareRevisionValue
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 6)";      
+            variant (aVP_Header) "LENGTHTO(aVP_Header,firmwareRevisionValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }  
+         
+  type record HostNameAVP
+  {
+    AVP_Header      aVP_Header, // type 7     
+    charstring      hostNameValue length (1..infinity)  
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 7)"; 
+            variant (aVP_Header) "LENGTHTO(aVP_Header,hostNameValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }          
+         
+  type record VendorNameAVP
+  {
+    AVP_Header      aVP_Header, // type 8       
+    charstring      vendorNameValue //length (0..infinity)   
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 8)";      
+            variant (aVP_Header) "LENGTHTO(aVP_Header,vendorNameValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }          
+         
+  type record AssignedTunnelIdAVP
+  {
+    AVP_Header      aVP_Header, // type 9   
+    INT2_BO_LAST    assignedTunnelIdValue     
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 9)";   
+            variant (aVP_Header) "LENGTHTO(aVP_Header,assignedTunnelIdValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }          
+         
+  type record ReceiveWindowSizeAVP
+  {
+    AVP_Header      aVP_Header, // type 10     
+    INT2_BO_LAST    windowSizeValue    
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 10)";   
+            variant (aVP_Header) "LENGTHTO(aVP_Header,windowSizeValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }            
+ 
+  type record ChallengeAVP
+  {
+    AVP_Header      aVP_Header, // type 11      
+    octetstring     challengeValue length (1..infinity)  
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 11)";    
+            variant (aVP_Header) "LENGTHTO(aVP_Header,challengeValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }            
+ 
+  type record ChallengeResponseAVP
+  {
+    AVP_Header      aVP_Header, // type 13  
+    OCT16           challengeResponseValue
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 13)";      
+            variant (aVP_Header) "LENGTHTO(aVP_Header,challengeResponseValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         } 
+         
+  type record Q931CauseCodeAVP    
+  {
+    AVP_Header      aVP_Header, // type 12    
+    OCT2            causeCode,
+    OCT1            causeMsg,
+    charstring      advisoryMsg optional    
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 12)";         
+            variant (aVP_Header) "LENGTHTO(aVP_Header,causeCode,causeMsg,advisoryMsg)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }      
+           
+  type record AssignedSessionIdAVP 
+  { 
+    AVP_Header      aVP_Header, // type 14     
+    INT2_BO_LAST    assignedSessionIdValue     
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 14)"; 
+            variant (aVP_Header) "LENGTHTO(aVP_Header,assignedSessionIdValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }   
+         
+  type record CallSerialNumberAVP
+  {
+    AVP_Header      aVP_Header, // type 15      
+    OCT4            callSerialNumberValue
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 15)"; 
+            variant (aVP_Header) "LENGTHTO(aVP_Header,callSerialNumberValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }                 
+                           
+  type record MinimumBPSAVP
+  {
+    AVP_Header      aVP_Header, // type 16        
+    OCT4            mimimumBPSValue
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 16)"; 
+            variant (aVP_Header) "LENGTHTO(aVP_Header,mimimumBPSValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }                  
+ 
+  type record MaximumBPSAVP
+  {
+    AVP_Header      aVP_Header, // type 17        
+    OCT4            maximumBPSValue
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 17)";   
+            variant (aVP_Header) "LENGTHTO(aVP_Header,maximumBPSValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)";       
+         }                  
+  
+  type record BearerTypeAVP
+  {
+    AVP_Header      aVP_Header, // type 18       
+    bitstring       reserved length (30),
+    BIT1            aBit,
+    BIT1            dBit       
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 18)";        
+            variant (aVP_Header) "LENGTHTO(aVP_Header,reserved,aBit,dBit)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+            variant (reserved) "FIELDLENGTH(30)";             
+            variant (reserved,aBit,dBit) "FIELDORDER(msb)";       
+         }  
+ 
+  type record FramingTypeAVP
+  {
+    AVP_Header      aVP_Header, // type 19  
+    bitstring       reserved length (30),  
+    BIT1            aBit,
+    BIT1            sBit               
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 19)";
+            variant (aVP_Header) "LENGTHTO(aVP_Header,reserved,aBit,sBit)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+            variant (reserved) "FIELDLENGTH(30)";             
+            variant (reserved,aBit,sBit) "FIELDORDER(msb)";       
+         }  
+  
+  type record CalledNumberAVP 
+  {
+    AVP_Header      aVP_Header, // type 21 
+    charstring      calledNumberValue    
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 21)";           
+            variant (aVP_Header) "LENGTHTO(aVP_Header,calledNumberValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }   
+ 
+  type record CallingNumberAVP 
+  {
+    AVP_Header      aVP_Header, // type 22 
+    charstring      callingNumberValue    
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 22)";          
+            variant (aVP_Header) "LENGTHTO(aVP_Header,callingNumberValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }   
+  
+  type record SUB_AddressAVP
+  {
+    AVP_Header      aVP_Header, // type 23   
+    charstring      sUB_AddressValue       
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 23)";        
+            variant (aVP_Header) "LENGTHTO(aVP_Header,sUB_AddressValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }  
+ 
+  type record TxConnectSpeedAVP
+  {
+    AVP_Header      aVP_Header, // type 24  
+    OCT4            bPS  
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 24)";  
+            variant (aVP_Header) "LENGTHTO(aVP_Header,bPS)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }   
+ 
+  type record  RxConnectSpeedAVP
+  {
+    AVP_Header      aVP_Header, // type 38    
+    OCT4            bPS    
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 38)";        
+            variant (aVP_Header) "LENGTHTO(aVP_Header,bPS)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }   
+
+  type record PhysicalChannelIdAVP
+  {
+    AVP_Header      aVP_Header, // type 25  
+    OCT4            physicalChannelIdValue  
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 25)";          
+            variant (aVP_Header) "LENGTHTO(aVP_Header,physicalChannelIdValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }    
+
+  type record PrivateGroupIdAVP
+  { 
+    AVP_Header      aVP_Header, // type 37
+    octetstring     privateGroupIdValue
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 37)";           
+            variant (aVP_Header) "LENGTHTO(aVP_Header,privateGroupIdValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         } 
+         
+  type record SequencingRequiredAVP         
+  { 
+    AVP_Header      aVP_Header // type 39        
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 39)";     
+            variant (aVP_Header) "LENGTHTO(aVP_Header)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }         
+         
+  type record InitialReceivedLCP_CONFREQ_AVP
+  {
+    AVP_Header      aVP_Header, // type 26 
+    octetstring     lCP_CONFREQ // structure ?
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 26)";
+            variant (aVP_Header) "LENGTHTO(aVP_Header,lCP_CONFREQ)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }                 
+         
+  type record LastSentLCP_CONFREQ_AVP
+  {
+    AVP_Header      aVP_Header, // type 27   
+    octetstring     lCP_CONFREQ // structure ?  
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 27)";    
+            variant (aVP_Header) "LENGTHTO(aVP_Header,lCP_CONFREQ)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         } 
+         
+  type record LastReceivedLCP_CONFREQ_AVP
+  {
+    AVP_Header      aVP_Header, // type 28   
+    octetstring     lCP_CONFREQ // structure ?      
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 28)";       
+            variant (aVP_Header) "LENGTHTO(aVP_Header,lCP_CONFREQ)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }          
+         
+  type record ProxyAuthenTypeAVP
+  {
+    AVP_Header      aVP_Header, // type 29     
+    INT2_BO_LAST    authenTypeValue
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 29)";        
+            variant (aVP_Header) "LENGTHTO(aVP_Header,authenTypeValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }          
+         
+  type record ProxyAuthenNameAVP        
+  {       
+    AVP_Header      aVP_Header, // type 30                                 
+    charstring      authenNameValue    
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 30)";          
+            variant (aVP_Header) "LENGTHTO(aVP_Header,authenNameValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         } 
+         
+  type record ProxyAuthenChallengeAVP
+  {
+    AVP_Header      aVP_Header, // type 31  
+    octetstring     challengeValue length (1..infinity)
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 31)";       
+            variant (aVP_Header) "LENGTHTO(aVP_Header,challengeValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }          
+         
+  type record ProxyAuthenIdAVP
+  {
+    AVP_Header      aVP_Header, // type 32 
+    INT2_BO_LAST    idValue  
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 32)";          
+            variant (aVP_Header) "LENGTHTO(aVP_Header,idValue)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }          
+                 
+  type record ProxyAuthenResponseAVP
+  {
+    AVP_Header      aVP_Header, // type 33  
+    octetstring     response 
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 33)";             
+            variant (aVP_Header) "LENGTHTO(aVP_Header,response)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }               
+                          
+  type record CallErrorsAVP
+  {  
+    AVP_Header      aVP_Header, // type 34  
+    OCT2            reserved, // 0
+    OCT4            cRCErrors,
+    OCT4            framingErrors,
+    OCT4            hardwareOverruns,
+    OCT4            bufferOverruns,
+    OCT4            timeoutErrors,
+    OCT4            alignmentErrors   
+  } with { 
+            variant "PRESENCE(aVP_Header.attributeType = 34)";      
+            variant (aVP_Header) "LENGTHTO(aVP_Header,reserved,cRCErrors,framingErrors,
+                                  hardwareOverruns,bufferOverruns,timeoutErrors,alignmentErrors)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }   
+          
+  type record ACCM_AVP 
+  {
+    AVP_Header      aVP_Header, // type 35
+    OCT2            reserved,  
+    OCT4            sendACCM,
+    OCT4            receiveACCM 
+  } with {
+            variant "PRESENCE(aVP_Header.attributeType = 35)";       
+            variant (aVP_Header) "LENGTHTO(aVP_Header,reserved,sendACCM,receiveACCM)"; 
+            variant (aVP_Header) "LENGTHINDEX(lengthValue)"; 
+         }  
+         
+
+ // ============================
+  type set of SCCRQ_AVP SCCRQ_AVPs;
+    
+  type union SCCRQ_AVP
+  {
+   ProtocolVersionAVP          protocolVersion,
+   HostNameAVP                 hostName,
+   FramingCapabilitiesAVP      framingCapabilities,
+   AssignedTunnelIdAVP         assignedTunnelId,   
+   BearerCapabilitiesAVP       bearerCapabilities,  //optional,
+   ReceiveWindowSizeAVP        receiveWindowSize,   //optional,
+   ChallengeAVP                challenge,           //optional,
+   TieBreakerAVP               tieBreaker,          //optional,
+   FirmwareRevisionAVP         firmwareRevision,    //optional,
+   VendorNameAVP               vendorName,          //optional 
+   RandomVectorAVP             randomVectorAVP      //optional 
+  }   
+
+  type set of SCCRP_AVP SCCRP_AVPs;
+
+  type union SCCRP_AVP
+  {
+   ProtocolVersionAVP          protocolVersion,
+   FramingCapabilitiesAVP      framingCapabilities,
+   HostNameAVP                 hostName,   
+   AssignedTunnelIdAVP         assignedTunnelId,      
+   BearerCapabilitiesAVP       bearerCapabilities,   //optional,
+   FirmwareRevisionAVP         firmwareRevision,     //optional,   
+   VendorNameAVP               vendorName,           //optional,     
+   ReceiveWindowSizeAVP        receiveWindowSize,    //optional,   
+   ChallengeAVP                challenge,            //optional,   
+   ChallengeResponseAVP        challengeResponse,    //optional 
+   RandomVectorAVP             randomVectorAVP       //optional
+  }
+
+  type set of SCCCN_AVP SCCCN_AVPs;
+
+  type union SCCCN_AVP
+  {
+   ChallengeResponseAVP        challengeResponse,    //optional  
+   RandomVectorAVP             randomVectorAVP       //optional
+  }
+   
+  type set of StopCCN_AVP StopCCN_AVPs; 
+
+  type union StopCCN_AVP
+  {
+   AssignedTunnelIdAVP         assignedTunnelId,   
+   ResultCodeAVP               resultCode,
+   RandomVectorAVP             randomVectorAVP     //optional
+  }
+
+ // type set HELLO_AVPs
+ // {
+ // }
+
+  type set of OCRQ_AVP OCRQ_AVPs;
+
+  type union OCRQ_AVP
+  {
+   AssignedSessionIdAVP        assignedSessionId,   
+   CallSerialNumberAVP         callSerialNumber,
+   MinimumBPSAVP               minimumBPS,
+   MaximumBPSAVP               maximumBPS,  
+   BearerTypeAVP               bearerType,
+   FramingTypeAVP              framingType, 
+   CalledNumberAVP             calledNumber, 
+   SUB_AddressAVP              sUB_Address,     //optional  
+   RandomVectorAVP             randomVector     //optional
+  }
+  
+  type set of OCRP_AVP OCRP_AVPs;   
+
+  type union OCRP_AVP
+  {
+   AssignedSessionIdAVP        assignedSessionId,  
+   PhysicalChannelIdAVP        physicalChannelId, //optional
+   RandomVectorAVP             randomVector       //optional
+  }
+
+  type set of OCCN_AVP OCCN_AVPs; 
+  
+  type union OCCN_AVP
+  {
+   TxConnectSpeedAVP                 txConnectSpeed,
+   FramingTypeAVP                    framingType, 
+   RxConnectSpeedAVP                 rxConnectSpeed, //optional,   
+   SequencingRequiredAVP             sequencingRequired, //optional   
+   RandomVectorAVP                   randomVector      //optional  
+  }
+
+
+  type set of ICRQ_AVP ICRQ_AVPs;
+
+  type union ICRQ_AVP
+  {
+   AssignedSessionIdAVP        assignedSessionId,      
+   CallSerialNumberAVP         callSerialNumber,
+   BearerTypeAVP               bearerType,    //optional,
+   PhysicalChannelIdAVP        physicalChannelId, //optional,
+   CallingNumberAVP            callingNumber, //optional,
+   CalledNumberAVP             calledNumber,  //optional,
+   SUB_AddressAVP              sUB_Address,    //optional 
+   RandomVectorAVP             randomVector    //optional
+  }
+
+
+  type set of ICRP_AVP ICRP_AVPs;
+
+  type union ICRP_AVP
+  {
+   AssignedSessionIdAVP         assignedSessionId,  
+   RandomVectorAVP              randomVector      
+  }
+
+  type set of ICCN_AVP ICCN_AVPs;
+
+  type union ICCN_AVP
+  {
+    TxConnectSpeedAVP                 txConnectSpeed,
+    FramingTypeAVP                    framingType,            
+    InitialReceivedLCP_CONFREQ_AVP    initialReceivedLCP_CONFREQ_AVP,
+    LastSentLCP_CONFREQ_AVP           lastSentLCP_CONFREQ_AVP, //optional,
+    LastReceivedLCP_CONFREQ_AVP       lastReceivedLCP_CONFREQ_AVP, //optional,
+    ProxyAuthenTypeAVP                proxyAuthenType, //optional,
+    ProxyAuthenNameAVP                proxyAuthenName, //optional,
+    ProxyAuthenChallengeAVP           proxyAuthenChallenge, //optional,
+    ProxyAuthenIdAVP                  proxyAuthenId, //optional,
+    ProxyAuthenResponseAVP            proxyAuthenResponse, //optional,
+    PrivateGroupIdAVP                 privateGroupId, //optional,
+    RxConnectSpeedAVP                 rxConnectSpeed, //optional,
+    SequencingRequiredAVP             sequencingRequired, //optional 
+    RandomVectorAVP                   randomVector       //optional  
+  }
+  
+  type set of CDN_AVP CDN_AVPs;
+
+  type union CDN_AVP
+  {
+    ResultCodeAVP               resultCode,   
+    AssignedSessionIdAVP        assignedSessionId, 
+    Q931CauseCodeAVP            q931CauseCode,   //optional 
+    RandomVectorAVP             randomVector  //optional
+  }
+
+  type set of WEN_AVP WEN_AVPs;
+
+  type union WEN_AVP
+  {
+    CallErrorsAVP        callErrors, 
+    RandomVectorAVP      randomVector   //optional
+  }
+  
+  type set of SLI_AVP SLI_AVPs;
+
+  type union SLI_AVP
+  {
+    ACCM_AVP              aCCM,
+    RandomVectorAVP       randomVector   //optional
+  }
+
+
+ // Control Messages ============================
+ 
+ 
+  type record SCCRQ 
+  {  
+    MessageTypeAVP  messageType,   
+    SCCRQ_AVPs      aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 1)"; }; 
+      
+  type record SCCRP 
+  {  
+   MessageTypeAVP  messageType,     
+   SCCRP_AVPs      aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 2)"; };    
+  
+         
+  type record SCCCN 
+  {  
+   MessageTypeAVP  messageType,     
+   SCCCN_AVPs      aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 3)"; };       
+  
+   
+  type record StopCCN 
+  {  
+   MessageTypeAVP  messageType,     
+   StopCCN_AVPs    aVPs 
+  } with { variant "PRESENCE (messageType.messageTypeValue = 4)"; };          
+  
+  
+  type record HELLO  
+  {  
+   MessageTypeAVP  messageType     
+  // HELLO_AVPs    aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 6)"; };       
+  
+   
+  type record OCRQ 
+  {  
+   MessageTypeAVP  messageType,     
+   OCRQ_AVPs       aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 7)"; };          
+  
+   
+  type record OCRP 
+  {  
+   MessageTypeAVP  messageType,     
+   OCRP_AVPs       aVPs 
+  } with { variant "PRESENCE (messageType.messageTypeValue = 8)"; };          
+   
+   
+  type record OCCN  
+  {  
+   MessageTypeAVP  messageType,     
+   OCCN_AVPs       aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 9)"; };         
+  
+   
+  type record ICRQ 
+  {  
+   MessageTypeAVP  messageType,     
+   ICRQ_AVPs       aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 10)"; };     
+  
+    
+  type record ICRP  
+  {  
+   MessageTypeAVP  messageType,     
+   ICRP_AVPs       aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 11)"; };          
+  
+    
+  type record ICCN 
+  {  
+   MessageTypeAVP  messageType,     
+   ICCN_AVPs       aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 12)"; };          
+  
+    
+  type record CDN  
+  {  
+   MessageTypeAVP  messageType,     
+   CDN_AVPs        aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 14)"; };         
+  
+    
+  type record WEN  
+  {  
+   MessageTypeAVP  messageType,     
+   WEN_AVPs        aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 15)"; };         
+  
+  
+  type record SLI 
+  {  
+   MessageTypeAVP  messageType,     
+   SLI_AVPs        aVPs
+  } with { variant "PRESENCE (messageType.messageTypeValue = 16)"; };       
+
+  type record ZLB
+  {
+  }
+  
+ // L2TP Header ============================
+         
+  type record L2TP_Offset   
+  {     
+    INT2_BO_LAST    offsetSize,    
+    octetstring     offsetPad     optional     
+  } with {  variant (offsetSize) "LENGTHTO(offsetPad)";}        
+  
+  
+  type record L2TP_Header
+  {
+    BIT1           pBit, //pBit (priority), 0 in ctrl messages
+    BIT1           oBit, //if oBit is 1 offset field is present, 0 in ctrl messages
+    BIT1           reserved, //'0'B
+    BIT1           sBit, //if sBit is 1 ns and nr fields are present, 1 in ctrl messages
+    BIT2           reserved2, //'0'B
+    BIT1           lBit, //if lBit is 1 lengthValuefield is present, 1 in ctrl messages
+    BIT1           tBit, // type of message (0=dataMessage, 1=controlMessage)  
+    BIT4           ver, //'0010'B
+    BIT4           reserved3, //'0'B
+    INT2_BO_LAST   lengthValue   optional, 
+    INT2_BO_LAST   tunnelId,
+    INT2_BO_LAST   sessionId,
+    INT2_BO_LAST   ns            optional,
+    INT2_BO_LAST   nr            optional,
+    L2TP_Offset    offset        optional    
+  } with {  
+           variant (lengthValue) "PRESENCE(lBit = '1'B)";         
+           variant (ns) "PRESENCE(sBit = '1'B)";
+           variant (nr) "PRESENCE(sBit = '1'B)";
+           variant (offset) "PRESENCE(oBit = '1'B)";       
+         }  
+                 
+ // L2TP PDU ============================  
+ 
+  type union ControlMessage
+  {   
+    SCCRQ             sCCRQ,
+    SCCRP             sCCRP,
+    SCCCN             sCCCN,
+    StopCCN           stopCCN,
+    HELLO             hELLO,
+    OCRQ              oCRQ,
+    OCRP              oCRP,
+    OCCN              oCCN,
+    ICRQ              iCRQ,
+    ICRP              iCRP,
+    ICCN              iCCN,
+    CDN               cDN,
+    WEN               wEN,
+    SLI               sLI,
+    ZLB               zLB       
+  } 
+  
+  type union L2TP_Body
+  {  
+    octetstring      dataMessage,
+    ControlMessage   controlMessage
+  }     
+  
+  type record PDU_L2TP 
+  {
+    L2TP_Header        header,
+    L2TP_Body          body
+  } with {  
+            variant (body)"CROSSTAG(dataMessage,    header.tBit = '0'B;
+                                    controlMessage, header.tBit = '1'B)"
+         } 
+                                  
+} with { encode "RAW"} // end of module