MME2 changes - Propped commits from openmme/paging branch. Added scripts
for code gen

Change-Id: Ie55032217232214ac8544ca76ea34335205329e4
diff --git a/scripts/GtpV2StackCodeGen/tts/datatypetemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/datatypetemplate.cpp.tt
new file mode 100644
index 0000000..14d1288
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/datatypetemplate.cpp.tt
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */
+
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/datatypetemplate.cpp.tt>
+ ******************************************************************************/
+#include "[% tempdata.fileName %].h"
+
+// TODO
+
+[% tempdata.className %]::[% tempdata.className %]()
+{
+    // TODO
+}
+
+[% tempdata.className %]::~[%tempdata.className %]() {
+    // TODO Auto-generated destructor stub
+}
+
+[% FOREACH type IN tempdata.DataTypeListAuto %]
+bool [%tempdata.className %]::encode[% type.typeName %](MsgBuffer &buffer, [% type.typeName %] const &data)
+{
+[% IF type.validationPresent == "y" -%]
+    if (!([% type.validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure: [% type.typeName %]\n"); 
+        return false; //TODO need to add validations
+    }
+[% END -%]   
+[% FOREACH Item IN type.sequence -%]
+[% IF Item.skipType == "y" -%]
+    buffer.skip[% Item.bitByte %]([% Item.skipValue %]);
+
+[% ELSE -%]
+[% IF Item.presence == "optional" -%]
+    if (data.[% Item.fieldName %]Present)
+    {
+
+[% IF Item.encodeConditional == "y" -%]
+        if ([% Item.encodeCondition %])
+        {
+
+[% IF Item.validationPresent == "y" -%]
+            if (!([% Item.validationRule %]))
+            {
+                errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n"); 
+                return false; //TODO need to add validations
+            }
+[% END -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+            buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %]);
+[% ELSE -%]
+            buffer.write[% Item.fieldType %](data.[% Item.fieldName %]);
+[% END -%]
+[% ELSE -%]
+            if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+            {
+                errorStream.add((char *)"Failed to encode [% Item.fieldName %]\n");
+                return false;
+            }
+[% END -%]
+
+        }
+    }
+[% ELSE -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+        buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %]);
+[% ELSE -%]
+        buffer.write[% Item.fieldType %](data.[% Item.fieldName %]);
+[% END -%]
+[% ELSE -%]
+        if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+        {
+            errorStream.add((char *)"Failed to encode [% Item.fieldName %]\n");
+            return false;
+        }
+
+[% END -%]
+    }
+[% END -%]
+[% ELSE -%]
+[% IF Item.encodeConditional == "y" -%]
+    if ([% Item.encodeCondition %])
+    {
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {    
+            errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n"); 
+            return false; //TODO need to add validations
+        }
+[% END -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+        buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %]);
+[% ELSE -%]
+        buffer.write[% Item.fieldType %](data.[% Item.fieldName %]);
+[% END -%]
+[% ELSE -%]
+        if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+        {
+            errorStream.add((char *)"Failed to encode [% Item.fieldName %]\n");
+            return false;
+        }
+
+[% END -%]
+    }
+
+[% ELSE -%]
+[% IF Item.validationPresent == "y" -%]
+    if (!([% Item.validationRule %]))
+    {
+         errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n"); 
+         return false; //TODO need to add validations
+    }
+[% END -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+    buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %]);
+[% ELSE -%]
+    buffer.write[% Item.fieldType %](data.[% Item.fieldName %]);
+[% END -%]
+[% ELSE -%]
+    if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+    {
+        errorStream.add((char *)"Failed to encode [% Item.fieldName %]\n");
+        return false;
+    }
+
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+    return true;
+}
+
+bool [%tempdata.className %]::decode[% type.typeName %](MsgBuffer &buffer,[% type.typeName %] &data,
+                         Uint16 length)
+{
+    
+    Uint16 typeBoundary = buffer.getCurrentIndex() + length;
+[% FOREACH Item IN type.sequence -%]
+[% IF Item.skipType == "y" -%]
+    buffer.skip[% Item.bitByte %]([% Item.skipValue %]);
+    if (buffer.getCurrentIndex() > typeBoundary)
+    {
+        errorStream.add((char *)"Attempt to read beyond type boundary: [% Item.fieldName %]\n");
+        return false;
+    }
+[% ELSE -%]
+[% IF Item.decodeConditional == "y" %]
+    if ([% Item.decodeCondition %])
+    {
+
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+        data.[% Item.fieldName %] = buffer.readBits([% Item.fieldSize %]);
+        if (buffer.getCurrentIndex() > typeBoundary)
+        {
+            errorStream.add((char *)"Attempt to read beyond type boundary: [% Item.fieldName %]\n");
+            return false;
+        }
+[% ELSE %]
+        buffer.read[% Item.fieldType %](data.[% Item.fieldName %]);
+        if (buffer.getCurrentIndex() > typeBoundary)
+        {
+            errorStream.add((char *)"Attempt to read beyond type boundary: [% Item.fieldName %]\n");
+            return false;
+        }
+[% END -%]
+[% ELSE -%]
+[% IF Item.length == "lengthLeft" -%]
+        Uint16 lengthLeft = typeBoundary - buffer.getCurrentIndex();
+[% END -%]
+[% IF Item.arrayType == "y" -%]
+        if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %], [% Item.count %])))
+[% ELSE -%]
+        if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %])))
+[% END -%]
+        {
+            errorStream.add((char *)"Failed to decode: [% Item.fieldName %]\n");
+            return false;
+        }
+[% END -%]
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {
+            errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+            return false; //TODO need to add validations
+        }
+[% END -%]
+[% IF Item.presence == "optional" -%]
+        data.[% Item.fieldName %]Present = true;
+[% END -%]
+
+    }
+[% ELSE -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+    data.[% Item.fieldName %] = buffer.readBits([% Item.fieldSize %]);
+    if (buffer.getCurrentIndex() > typeBoundary)
+    {
+         errorStream.add((char *)"Attempt to read beyond type boundary: [% Item.fieldName %]\n");
+         return false;
+    }
+[% ELSE %]
+    buffer.read[% Item.fieldType %](data.[% Item.fieldName %]);
+    if (buffer.getCurrentIndex() > typeBoundary)
+    {
+         errorStream.add((char *)"Attempt to read beyond type boundary: [% Item.fieldName %]\n");
+         return false;
+    }
+[% END -%]
+[% ELSE -%]
+[% IF Item.length == "lengthLeft" -%]
+ Uint16   lengthLeft = typeBoundary - buffer.getCurrentIndex();
+[% END -%]
+[% IF Item.arrayType == "y" -%]
+    if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %], [% Item.count %])))
+[% ELSE -%]
+    if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %])))
+[% END -%]
+    {
+        errorStream.add((char *)"Failed to decode: [% Item.fieldName %]\n");
+        return false;
+    }
+[% END -%]
+[% IF Item.validationPresent == "y" -%]
+    if (!([% Item.validationRule %]))
+    {
+         errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+         return false; //TODO need to add validations
+    }
+[% END -%]
+[% IF Item.presence == "optional" -%]
+    data.[% Item.fieldName %]Present = true;
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+
+[% IF validationPresent == "y" -%]
+    if (!([% validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure at IE: [%tempdata.className %]\n");
+        return false;
+    }
+[% END -%]
+  return true;
+}
+
+void [%tempdata.className %]::display[% type.typeName %]_v([% type.typeName %] const &data, Debug &stream)
+{
+    stream.incrIndent();
+    stream.add((char *)"[% type.typeName %]:");
+    stream.incrIndent();
+    stream.endOfLine();
+[% FOREACH Item IN type.sequence -%]
+[% IF Item.skipType != "y" -%]
+[% IF Item.presence == "optional" -%]
+    if (data.[% Item.fieldName %]Present)
+    {
+[% IF Item.encodeConditional == "y" %]
+        if ([% Item.encodeCondition %])
+        {
+[% IF Item.leafType == "y" -%]
+            stream.add((char *)"[% Item.fieldName %] = ");
+            stream.add(data.[% Item.fieldName %]);
+            stream.endOfLine();
+[% ELSE -%]
+            DataTypeCodecUtils::display[% Item.fieldType %]_v(data.[% Item.fieldName %], stream);  
+[% END -%]
+        }
+    }
+[%ELSE-%]
+[% IF Item.leafType == "y" -%]
+        stream.add((char *)"[% Item.fieldName %] = ");
+        stream.add(data.[% Item.fieldName %]);
+        stream.endOfLine();
+[% ELSE -%]
+         DataTypeCodecUtils::display[% Item.fieldType %]_v(data.[% Item.fieldName %], stream);
+[% END -%]
+    }
+
+[% END -%]
+[% ELSE -%]
+[% IF Item.encodeConditional == "y" %]
+    if ([% Item.encodeCondition %])
+    {
+[% IF Item.leafType == "y" -%]
+        stream.add((char *)"[% Item.fieldName %] = ");
+        stream.add(data.[% Item.fieldName %]);
+        stream.endOfLine();
+[% END -%]
+    }
+[%ELSE-%]
+[% IF Item.leafType == "y" -%]
+    stream.add((char *)"[% Item.fieldName %] = ");
+    stream.add(data.[% Item.fieldName %]);
+    stream.endOfLine();
+[% END -%]
+[% END -%]    
+[% END -%]
+[% END -%]
+[% END -%]
+    stream.decrIndent();
+    stream.decrIndent();
+}
+[% END %]
+
+[% FOREACH arrayType IN tempdata.arrayTypeList %]
+bool [%tempdata.className %]::encode[% arrayType.typeName %](MsgBuffer &buffer,
+ [% arrayType.typeName %] const &data)
+{
+    Uint16 i;
+    for (i = 0; i < data.count; i++)
+    {
+[% IF arrayType.leafType == "y" -%]
+        buffer.write[% arrayType.subType %](data.values[i]);
+[% ELSE -%]
+        if (!(DataTypeCodecUtils::encode[% arrayType.subType %](buffer, data.values[i])))
+        {
+            errorStream.add((char *)"Failed to encode [% arrayType.typeName %]\n");
+            return false;
+        }
+[% END -%]
+    }
+    return true;
+}
+
+bool [%tempdata.className %]::decode[% arrayType.typeName %](MsgBuffer &buffer,
+ [% arrayType.typeName %] &data, Uint16 length, Uint16 count)
+{
+    Uint16 i = 0;
+    data.count = 0;
+    bool readTillEnd = (count == 0);
+    Uint16 startIndex = buffer.getCurrentIndex();
+    Uint16 typeBoundary = startIndex+length;
+    
+    while ((i < count)||(readTillEnd && (buffer.getCurrentIndex() < typeBoundary)))
+    {
+[% IF arrayType.leafType == "y" -%]
+        buffer.read[% arrayType.subType %](data.values[i]);
+[% ELSE -%]
+        Uint16 lengthLeft = typeBoundary - buffer.getCurrentIndex();
+        [% IF arrayType.arrayType == "y" -%]
+         if (!(DataTypeCodecUtils::decode[% arrayType.subType %](buffer, data.values[i], lengthLeft, data.count)))
+         [% ELSE -%]
+         if (!(DataTypeCodecUtils::decode[% arrayType.subType %](buffer, data.values[i], lengthLeft)))
+         [% END -%]
+        
+        {
+            errorStream.add((char *)"Failed to encode [% arrayType.typeName %]\n");
+            return false;
+        }
+[% END -%]
+        if (buffer.getCurrentIndex() > typeBoundary)
+        {
+            errorStream.add((char *)"Attempt to read beyond type boundary:[% arrayType.typeName %]\n");
+            return false;
+        }
+        data.count++;
+        i++;
+    }
+	return true;
+}
+
+void [%tempdata.className %]::display[% arrayType.typeName %]_v([% arrayType.typeName %] const &data, Debug &stream)
+{
+    stream.incrIndent();
+    stream.add((char *)"[% arrayType.typeName %]: Count: ");
+    stream.add(data.count);
+    stream.incrIndent();
+    stream.endOfLine();
+[% IF arrayType.leafType == "y" -%]    
+    Uint16 i;
+    for (i = 0; i < data.count; i++)
+    {
+        stream.add(data.values[i]);
+        stream.endOfLine();     
+    }
+[% END -%]
+    stream.decrIndent();
+    stream.decrIndent();
+}
+[% END %]
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/datatypetemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/datatypetemplate.h.tt
new file mode 100644
index 0000000..a1fbf4b
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/datatypetemplate.h.tt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/datatypetemplate.h.tt>
+ ******************************************************************************/
+
+#ifndef [% tempdata.classNameUC %]_H_
+#define [% tempdata.classNameUC %]_H_
+
+#include <sstream>
+#include <msgBuffer.h>
+#include "gtpV2IeDataTypes.h"
+#include "gtpV2DataTypes.h"
+#include "manual/gtpV2DataTypes_Manual.h"
+
+//TODO Includes
+
+class DataTypeCodecUtils {
+public:
+    [% tempdata.className %]();
+    virtual ~[% tempdata.className %]();
+
+[% FOREACH type IN tempdata.DataTypeListAuto %]
+    static bool encode[% type.typeName %](MsgBuffer &buffer, [% type.typeName %] const &data);
+    static bool decode[% type.typeName %](MsgBuffer &buffer, [% type.typeName %] &data,
+                 Uint16 length);
+    static void display[% type.typeName %]_v([% type.typeName %] const &data, Debug &stream);
+[% END %]
+
+    // The following methods are generated to encode, decode and display array types
+[% FOREACH arrayType IN tempdata.arrayTypeList %]
+    static bool encode[% arrayType.typeName %](MsgBuffer &buffer, [% arrayType.typeName %] const &data);
+    static bool decode[% arrayType.typeName %](MsgBuffer &buffer, [% arrayType.typeName %] &data,
+                 Uint16 length, Uint16 count);
+    static void display[% arrayType.typeName %]_v([% arrayType.typeName %] const &data, Debug &stream);
+
+[% END -%]
+
+    // The following methods are to be written manually
+    // See DataTypeCodecUtils_Manual.cc for implementation
+[% FOREACH type IN tempdata.DataTypeListManual %]
+    static bool encode[% type.typeName %](MsgBuffer &buffer, [% type.typeName %] const &data);
+    static bool decode[% type.typeName %](MsgBuffer &buffer, [% type.typeName %] &data,
+                 Uint16 length);
+    static void display[% type.typeName %]_v([% type.typeName %] const &data, Debug &stream);
+[% END %]
+         
+};
+
+#endif /*[% tempdata.classNameUC %]_H_*/
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/grpIeDataTypetemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/grpIeDataTypetemplate.h.tt
new file mode 100644
index 0000000..55943ca
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/grpIeDataTypetemplate.h.tt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/grpIeDataTypetemplate.h.tt>
+ ******************************************************************************/
+#ifndef GTPV2GRPIEDATATYPES_H_
+#define GTPV2GRPIEDATATYPES_H_
+
+#include "../../gtpV2Codec/ieClasses/gtpV2IeDataTypes.h"
+
+[% FOREACH grpIe IN tempdata.grpList -%]
+typedef struct
+{
+[% FOREACH iePresence IN grpIe.iePresenceList -%]
+    bool [% iePresence %];    
+[% END -%]
+
+[% FOREACH ie IN grpIe.ieList -%]
+    [% ie.ieTypeName %] [% ie.ieVarName %];    
+[% END -%]
+
+}[% grpIe.grpIeName %];
+
+[% END -%]
+
+//Ie Type Constants
+[% FOREACH ie IN tempdata.grpTypeList -%]
+static const  Uint8  [% ie.grpIeTypeName %] = [% ie.grpIeTypeValue %];    
+[% END -%]
+
+
+#endif 
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.cpp.tt
new file mode 100644
index 0000000..60935b4
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.cpp.tt
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */ 
+
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.cpp.tt>
+ ******************************************************************************/
+ 
+#include "[% tempdata.fileName %].h"
+#include "manual/gtpV2Ie.h"
+#include "gtpV2IeFactory.h"
+[% FOREACH ieData IN tempdata.ieList -%]
+#include "[% ieData.ieFileName %].h"
+[% END -%]
+
+[% tempdata.msgClassName %]::
+[% tempdata.msgClassName %]()
+{
+[% PROCESS MandIeList %]
+}
+
+[% tempdata.msgClassName %]::
+~[% tempdata.msgClassName %]()
+{
+
+}
+bool [% tempdata.msgClassName %]::
+encode[% tempdata.msgClassName %](MsgBuffer &buffer,
+                         [% tempdata.msgClassName %]Data
+                          const &data)
+{
+    bool rc = false;
+    GtpV2IeHeader header;
+    Uint16 startIndex = 0;
+    Uint16 endIndex = 0;
+    Uint16 length = 0;
+[% FOREACH ieData IN tempdata.ieList -%]
+
+[% IF ieData.iePresence != 'M' -%]
+    if (data.[% ieData.ieVarName %]IePresent)
+    {
+        [% INCLUDE tts/msgEncode.tt FILTER indent%]
+        if (!(rc))
+        {
+          errorStream.add((char *)"Failed to encode IE: [% ieData.ieVarName %]\n");
+          return false;
+        }
+    }
+[% ELSE %]
+    [% INCLUDE tts/msgEncode.tt -%]
+    if (!(rc))
+    {
+        errorStream.add((char *)"Failed to encode IE: [% ieData.ieVarName %]\n");
+        return false;
+    }
+[% END -%]
+[% END -%]
+    return rc;
+}
+
+bool [% tempdata.msgClassName %]::
+decode[% tempdata.msgClassName %](MsgBuffer &buffer,
+                         [% tempdata.msgClassName %]Data 
+                         &data, Uint16 length)
+{
+
+    bool rc = false;
+    GtpV2IeHeader ieHeader;
+    set<Uint16> mandatoryIeLocalList = mandatoryIeSet;
+    while (buffer.lengthLeft() > IE_HEADER_SIZE)
+    {
+        GtpV2Ie::decodeGtpV2IeHeader(buffer, ieHeader);
+        if (ieHeader.length > buffer.lengthLeft())
+        {
+            // We do not have enough bytes left in the message for this IE
+            errorStream.add((char *)"IE Length exceeds beyond message boundary\n");
+            errorStream.add((char *)"  Offending IE Type: ");
+            errorStream.add(ieHeader.ieType);
+            errorStream.add((char *)"\n  Ie Length in Header: ");
+            errorStream.add(ieHeader.length);
+            errorStream.add((char *)"\n  Bytes left in message: ");
+            errorStream.add(buffer.lengthLeft());
+            errorStream.endOfLine();
+            return false;
+        }
+    
+        switch (ieHeader.ieType){
+[% FOREACH ieTypeEntry IN tempdata.ieTypeList -%]
+            case [% ieTypeEntry %]IeType:
+            {
+                [% ieTypeEntry %]Ie ieObject =
+                dynamic_cast<
+                [% ieTypeEntry %]Ie&>(GtpV2IeFactory::getInstance().
+                         getIeObject([% ieTypeEntry %]IeType));
+[% SET first = 1 -%]
+[% FOREACH ieTypeData IN tempdata.ieList -%]
+[% IF ieTypeData.ieType == ieTypeEntry -%] 
+
+[% IF first == 1 -%]
+[% SET first = 0 %]
+                if(ieHeader.instance == [% ieTypeData.instance %])
+[% ELSE -%]
+                else if(ieHeader.instance == [% ieTypeData.instance %])
+[% END -%]
+                {
+
+                [% INCLUDE tts/msgDecode.tt %]
+[% IF ieTypeData.ieCardinality == 1 %][% IF ieTypeData.iePresence != "M" -%]
+                    data.[% ieTypeData.ieVarName %]IePresent = true;
+[% END %][% END -%]
+                    if (!(rc))
+                    {
+                        errorStream.add((char *)"Failed to decode IE: [% ieTypeData.ieVarName %]\n");
+                        return false;
+                    }
+[% IF ieTypeData.iePresence == 'M' -%]
+                    Uint16 mandIe = [% ieTypeEntry %]IeType;
+                    mandIe = (mandIe << 8) | [% ieTypeData.instance %];
+                    mandatoryIeLocalList.erase(mandIe);
+[% END -%]
+                }
+[% END -%]
+[% END -%] 
+                else
+                {
+                    // Unknown IE instance print error TODO
+                    errorStream.add((char *)"Unknown IE Type: ");
+                    errorStream.add(ieHeader.ieType);
+                    errorStream.endOfLine();
+                    buffer.skipBytes(ieHeader.length);
+                }
+                break;
+            }
+[% END -%]
+            default:
+            {
+            // Unknown IE print error
+            errorStream.add((char *)"Unknown IE Type: ");
+            errorStream.add(ieHeader.ieType);
+            errorStream.endOfLine();
+            buffer.skipBytes(ieHeader.length);
+            }
+        }
+    }
+    if (!mandatoryIeLocalList.empty())
+    {
+        // some mandatory IEs are missing
+        errorStream.add((char *)"Missing Mandatory IEs:");
+        errorStream.endOfLine();
+        while (!mandatoryIeLocalList.empty())
+        {
+            Uint16 missingMandIe = *mandatoryIeLocalList.begin ();
+            mandatoryIeLocalList.erase (mandatoryIeLocalList.begin ());
+            Uint16 missingInstance = missingMandIe & 0x00FF;
+            Uint16 missingIeType = (missingMandIe >> 8);
+            errorStream.add ((char *)"Missing Ie type: ");
+            errorStream.add (missingIeType);
+            errorStream.add ((char *)"  Instance: ");
+            errorStream.add (missingInstance);
+            errorStream.endOfLine();
+        }
+        rc = false;
+    
+    }
+    return rc; 
+}
+
+void [% tempdata.msgClassName %]::
+display[% tempdata.msgClassName %]Data_v
+([% tempdata.msgClassName %]Data const &data, Debug &stream)
+{
+    stream.incrIndent();
+    stream.add((char *)"[% tempdata.msgClassName %]:");
+    stream.endOfLine();
+    stream.incrIndent();
+[% FOREACH ieData IN tempdata.ieList -%]
+
+[% IF ieData.iePresence != 'M' -%][% IF ieData.ieCardinality == 1 -%]
+    if (data.[% ieData.ieVarName %]IePresent)
+    {
+
+[% IF ieData.ieCardinality == 1 -%]
+        stream.add((char *)"[% ieData.ieVarName %]:");
+        stream.endOfLine();
+        [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+        dynamic_cast<
+        [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+    [% PROCESS ieDisplay_grp %]
+[% ELSE -%]
+        for (Uint8 i = 0; i < data.[% ieData.ieVarName %]Count; i++)
+        {
+            stream.add((char *)"IE -  [% ieData.ieVarName %]:");
+            stream.endOfLine();
+            [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+            dynamic_cast<[% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+        [% PROCESS ieDisplay_grp %]
+        }
+[% END -%]
+    }
+[% ELSE -%]
+[% IF ieData.ieCardinality == 1 -%]
+    stream.add((char *)"[% ieData.ieVarName %]:");
+    stream.endOfLine();
+    [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+    dynamic_cast<
+    [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+[% PROCESS ieDisplay_grp -%]
+[% ELSE -%]
+    for (Uint8 i = 0; i < data.[% ieData.ieVarName %]Count; i++)
+    {
+        stream.add((char *)"IE -  [% ieData.ieVarName %]:");
+        stream.endOfLine();
+        [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+        dynamic_cast<[% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+    [% PROCESS ieDisplay_grp -%]
+    }
+[% END -%]
+[% END %][% END -%]
+[% END -%]
+
+    stream.decrIndent();
+    stream.decrIndent();
+}
+
+
+[% BLOCK ieDisplay_grp -%]
+[% IF ieData.grouped == "Yes" -%]
+    [% ieData.grpIeInstClassName %] groupedIeInstance =
+    dynamic_cast<
+    [% ieData.grpIeInstClassName %]&>([% ieData.ieLocalVar %].getGroupedIe(msgType, [% ieData.instance %]));
+    groupedIeInstance.display[% ieData.grpIeInstClassName %]Data_v(data.[% ieData.ieVarName %][% PROCESS cardinalIndex %], stream);
+[% ELSE -%]
+    [% ieData.ieLocalVar %].display[% ieData.ieType %]Ie_v(data.[% ieData.ieVarName %][% PROCESS cardinalIndex %], stream);
+[% END -%]
+[% END -%]
+
+[% BLOCK cardinalIndex -%]
+[% IF ieData.ieCardinality != 1 %][i][% END -%]
+[% END -%]
+
+
+[% BLOCK MandIeList -%]
+[% SET first = 1 -%]
+[% FOREACH ieData IN tempdata.ieList -%]
+[% IF ieData.iePresence == 'M' -%]
+[% IF first == 1 -%]
+    Uint16 mandIe;
+[% SET first = 0 -%]
+[% END -%]
+    mandIe = [% ieData.ieType %]IeType;
+    mandIe = (mandIe << 8) | [% ieData.instance %]; // [% ieData.ieVarName %]
+    mandatoryIeSet.insert(mandIe);
+[% END -%]
+[% END -%]
+[% END -%]
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.h.tt
new file mode 100644
index 0000000..a1549e8
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.h.tt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */ 
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/grpieinsttemplate.h.tt>
+ ******************************************************************************/
+#ifndef [% tempdata.classNameUC %]_H_
+#define [% tempdata.classNameUC %]_H_
+
+#include <set>
+#include <sstream>
+#include "manual/gtpV2GroupedIe.h"
+#include <msgBuffer.h>
+#include "gtpV2GrpIeDataTypes.h"
+#include "../msgClasses/gtpV2MsgDataTypes.h"
+
+class [% tempdata.msgClassName %]:public GtpV2GroupedIe
+{
+public:
+    [% tempdata.msgClassName %]();
+    virtual ~[% tempdata.msgClassName %]();
+    bool encode[% tempdata.msgClassName %](MsgBuffer &buffer,
+                             [% tempdata.msgClassName %]Data
+                              const &data);
+
+    bool decode[% tempdata.msgClassName %] (MsgBuffer &buffer,
+                             [% tempdata.msgClassName %]Data 
+                             & data, Uint16 length);
+
+    void display[% tempdata.msgClassName %]Data_v
+    ([% tempdata.msgClassName %]Data const &data,
+     Debug &stream);
+
+private:
+    set <Uint16> mandatoryIeSet;
+};
+
+#endif
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/grpietemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/grpietemplate.cpp.tt
new file mode 100644
index 0000000..9a68e5a
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/grpietemplate.cpp.tt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */ 
+
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/grpietemplate.cpp.tt>
+ ******************************************************************************/
+#include "[% tempdata.fileName %].h"
+#include "gtpV2GrpIeDataTypes.h"
+#include "manual/gtpV2GroupedIe.h"
+[%fileList =tempdata.fileName -%]
+
+[% FOREACH inst IN tempdata.$fileList -%]
+#include "[% inst.fileName %].h"
+[% END -%]
+
+[% tempdata.className %]::[% tempdata.className %]()
+{
+    ieType = [% tempdata.className %]Type;
+   
+[% FOREACH inst IN tempdata.$fileList -%]
+    [% inst.className %]* [% inst.fileName %]_p = new ([% inst.className %]);
+    insertGroupedIeObject([% inst.msgType %], [% inst.instance %], [% inst.fileName %]_p);
+[% END -%]
+}
+
+[% tempdata.className %]::~[% tempdata.className %]() {
+// TODO Auto-generated destructor stub
+}
+
+GtpV2GroupedIe& [% tempdata.className %]::getGroupedIe(Uint8 msgType, Uint8 instance)
+{
+    std::map<Uint16, GtpV2GroupedIe*>::iterator it;
+    Uint16 key = msgType;
+    key = (key << 8) + instance;
+    it = groupedIeObjectContainer.find(key);
+    return *(it->second);
+}
+
+void [% tempdata.className %]::insertGroupedIeObject(Uint8 msgType, Uint8 instance, GtpV2GroupedIe* grpIe_p)
+{
+
+    Uint16 key = msgType;
+    key = (key << 8) + instance;
+
+    groupedIeObjectContainer.insert(std::pair<Uint16, GtpV2GroupedIe*>(key, grpIe_p));
+
+}  
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/grpietemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/grpietemplate.h.tt
new file mode 100644
index 0000000..f8105c5
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/grpietemplate.h.tt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/grpietemplate.h.tt>
+ ******************************************************************************/
+#ifndef [% tempdata.classNameUC %]_H_
+#define [% tempdata.classNameUC %]_H_
+
+#include <map>
+#include "manual/gtpV2Ie.h"
+#include "manual/gtpV2GroupedIe.h"
+#include "gtpV2DataTypes.h"
+
+class [% tempdata.className %]:public GtpV2Ie
+{
+public:
+    [% tempdata.className %] ();
+    virtual ~ [% tempdata.className %] ();
+
+    GtpV2GroupedIe & getGroupedIe (Uint8 msgType, Uint8 instance);
+    void insertGroupedIeObject (Uint8 msgType, Uint8 instance,
+                GtpV2GroupedIe * grpIe_p);
+
+private:
+    map < Uint16, GtpV2GroupedIe * >groupedIeObjectContainer;   // map[msgType || instance]
+};
+
+#endif
diff --git a/scripts/GtpV2StackCodeGen/tts/ieDataTypetemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/ieDataTypetemplate.h.tt
new file mode 100644
index 0000000..99b2c7b
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/ieDataTypetemplate.h.tt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/ieDataTypetemplate.h.tt>
+ ******************************************************************************/
+#ifndef GTPV2IEDATATYPES_H_
+#define GTPV2IEDATATYPES_H_
+
+#include "gtpV2DataTypes.h"
+#include "manual/gtpV2DataTypes_Manual.h"
+
+[% FOREACH ie IN tempdata.ieList -%]
+typedef struct
+{
+[% FOREACH ieField IN ie.varList -%]
+[% IF ieField.presence == "optional" -%]
+    bool [% ieField.varName %]Present;
+[% END -%]
+    [% ieField.varType %] [% ieField.varName %];    
+[% END -%]
+
+}[% ie.ieName %];
+
+[% END -%]
+
+//Ie Type Constants
+[% FOREACH ie IN tempdata.ieTypeList -%]
+static const  Uint8  [% ie.ieName %] = [% ie.value %];    
+[% END -%]
+
+
+#endif 
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.cpp.tt
new file mode 100644
index 0000000..5ecde81
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.cpp.tt
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */
+ 
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.cpp.tt>
+ ******************************************************************************/
+
+#include <map>
+#include "gtpV2IeFactory.h"
+#include "manual/gtpV2Ie.h"
+#include "gtpV2GrpIeDataTypes.h"
+[% FOREACH ie IN tempdata.ieList -%]
+#include "[% ie.ieFileName %].h"
+[% END -%]
+
+GtpV2IeFactory::GtpV2IeFactory() 
+{
+    //Create Message Objects    
+[% FOREACH ie IN tempdata.ieList -%]
+    [% ie.className %]* [% ie.ieFileName %]_p = new ([% ie.className %]);
+    ieObjectContainer.insert(std::pair<Uint8, GtpV2Ie*>([% ie.className %]Type, [% ie.ieFileName %]_p));
+
+[% END -%]
+
+}
+
+GtpV2IeFactory::~GtpV2IeFactory() {
+    // TODO clean up the allocated memory for message objects
+}
+
+GtpV2IeFactory& GtpV2IeFactory::getInstance()
+{
+    static GtpV2IeFactory gtpV2IeFactory;
+    return gtpV2IeFactory;
+}
+
+GtpV2Ie& GtpV2IeFactory::getIeObject(Uint8 ieType)
+{
+    std::map<Uint8, GtpV2Ie*>::iterator it;
+    it = ieObjectContainer.find(ieType);
+    return *(it->second);
+}
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.h.tt
new file mode 100644
index 0000000..b04eb47
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.h.tt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/iefactorytemplate.h.tt>
+ ******************************************************************************/
+#ifndef GTPV2IEFACTORY_H_
+#define GTPV2IEFACTORY_H_
+
+#include <map>
+#include "manual/gtpV2Ie.h"
+
+class GtpV2IeFactory {
+public:
+    GtpV2IeFactory();
+    virtual ~GtpV2IeFactory();
+
+    static GtpV2IeFactory& getInstance();
+
+    GtpV2Ie& getIeObject(Uint8 ieType);
+
+private:
+
+    map<Uint8, GtpV2Ie*> ieObjectContainer;
+
+};
+
+
+#endif /* GTPV2MSGFACTORY_H_ */
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/ietemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/ietemplate.cpp.tt
new file mode 100644
index 0000000..2e1a131
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/ietemplate.cpp.tt
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/ietemplate.cpp.tt>
+ ******************************************************************************/
+
+#include "[% tempdata.fileName %].h"
+#include "dataTypeCodecUtils.h"
+
+[% tempdata.className %]::[% tempdata.className %]() 
+{
+    ieType = [% tempdata.ieTypeVal %];
+    // TODO
+
+}
+
+[% tempdata.className %]::~[% tempdata.className %]() {
+    // TODO Auto-generated destructor stub
+}
+
+bool [% tempdata.className %]::encode[% tempdata.className %](MsgBuffer &buffer, [% tempdata.className %]Data const &data)
+{
+[% IF validationPresent == "y" -%]
+    if (!([% validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure at IE : [% tempdata.className %]\n");
+        return false; 
+    }[% END -%]
+[% FOREACH Item IN tempdata.sequence -%]
+[% IF Item -%]
+[% IF Item.skipType == "y" -%]
+    buffer.skip[% Item.bitByte %]([% Item.skipValue %]);
+
+[% ELSE -%]
+[% IF Item.presence == "optional" -%]
+    if (data.[% Item.fieldName %]Present)
+    {
+[% IF Item.encodeConditional == "y" -%]
+        if ([% Item.encodeCondition %])
+        {
+[% IF Item.leafType == "y" -%]
+[% IF Item.validationPresent == "y" -%]
+            if (!([% Item.validationRule %]))
+            {
+                errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+                return false; 
+            }
+[% END -%]
+[% IF Item.bitField == "y" -%]
+            if(!(buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %])))
+            {
+                errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+                return false;
+            }
+[% ELSE -%]
+            if (!(buffer.write[% Item.fieldType %](data.[% Item.fieldName %])))
+            {
+                errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+                return false;
+            }
+[% END -%]
+[% ELSE -%]
+[% IF Item.validationPresent == "y" -%]
+            if (!([% Item.validationRule %]))
+            {
+                errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+                return false; 
+            }
+[% END -%]
+            if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+            {
+                errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+                return false;
+            }
+[% END -%]
+        }
+    }
+[% ELSE -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {
+            errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+            return false; 
+        }
+[% END -%]
+[% IF Item.bitField == "y" -%]
+        if(!(buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %])))
+        {
+            errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+            return false;
+        }
+[% ELSE -%]
+        if (!(buffer.write[% Item.fieldType %](data.[% Item.fieldName %])))
+        {
+            errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+            return false;
+        }
+[% END -%]
+[% ELSE -%]
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {
+            errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+            return false; 
+        }
+[% END -%]
+        if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+        {
+            errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+            return false;
+        }
+[% END -%]
+    }
+[% END -%]
+[% ELSE -%]
+[% IF Item.encodeConditional == "y" -%]
+    if ([% Item.encodeCondition %])
+    {
+[% IF Item.leafType == "y" -%]
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {
+            errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+            return false; 
+        }
+[% END -%]
+[% IF Item.bitField == "y" -%]
+        if(!(buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %])))
+        {
+            errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+            return false;
+        }
+[% ELSE -%]
+        if (!(buffer.write[% Item.fieldType %](data.[% Item.fieldName %])))
+        {
+    errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+    return false;
+        }
+[% END -%]
+[% ELSE -%]
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {
+            errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+            return false; 
+        }
+[% END -%]
+        if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+        {
+            errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+            return false;
+        }
+[% END -%]
+    }
+[% ELSE -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.validationPresent == "y" -%]
+    if (!([% Item.validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+        return false; 
+    }
+[% END -%]
+[% IF Item.bitField == "y" -%]
+    if(!(buffer.writeBits(data.[% Item.fieldName %], [% Item.fieldSize %])))
+    {
+        errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+        return false;
+    }
+[% ELSE -%]
+    if (!(buffer.write[% Item.fieldType %](data.[% Item.fieldName %])))
+    {
+        errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+        return false;
+    }
+[% END -%]
+[% ELSE -%]
+[% IF Item.validationPresent == "y" -%]
+    if (!([% Item.validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure: [% Item.fieldName %]\n");
+        return false; 
+    }
+[% END -%]
+    if (!(DataTypeCodecUtils::encode[% Item.fieldType %](buffer, data.[% Item.fieldName %])))
+    {
+    errorStream.add((char *)"Encoding of [% Item.fieldName %] failed\n");
+    return false;
+    }
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+[% END %]
+    return true;
+}
+
+bool [% tempdata.className %]::decode[% tempdata.className %](MsgBuffer &buffer, [% tempdata.className %]Data &data, Uint16 length)
+{ 
+[%- flag = 0 -%]
+    
+    // TODO optimize the length checks
+    
+    Uint16 ieBoundary = buffer.getCurrentIndex() + length;
+[% FOREACH Item IN tempdata.sequence -%]
+[% IF Item.length == "lengthLeft" -%][%- IF flag == 0 %]
+    Uint16 lengthLeft = length;
+    [%- flag = 1 %]
+[% END -%][% END -%]
+[% IF Item.skipType == "y" -%]
+    buffer.skip[% Item.bitByte %]([% Item.skipValue %]);
+    if (buffer.getCurrentIndex() > ieBoundary)
+    {
+        errorStream.add((char *)"Attempt to read beyond IE boundary: [% Item.fieldName %]\n");
+        return false;
+    }
+
+[% ELSE -%]
+[% IF Item.decodeConditional == "y" %]
+    if ([% Item.decodeCondition %])
+    {
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+        data.[% Item.fieldName %] = buffer.readBits([% Item.fieldSize %]);
+        // confirm that we are not reading beyond the IE boundary
+        if (buffer.getCurrentIndex() > ieBoundary)
+        {
+            errorStream.add((char *)"Attempt to read beyond IE boundary: [% Item.fieldName %]\n");
+            return false;
+        }
+[% ELSE %]
+        buffer.read[% Item.fieldType %](data.[% Item.fieldName %]);
+        if (buffer.getCurrentIndex() > ieBoundary)
+        {
+            errorStream.add((char *)"Attempt to read beyond IE boundary: [% Item.fieldName %]\n");
+            return false;
+        }
+[% END -%]
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {
+            errorStream.add((char *)"Data validation failure : [% Item.fieldName %]\n");
+            return false; //TODO need to add validations
+        }
+[% END -%]
+[% ELSE -%]
+[% IF Item.length == "lengthLeft" -%]
+        lengthLeft = ieBoundary - buffer.getCurrentIndex();
+[% END -%]
+[% IF Item.arrayType == "y" -%]
+        if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %], [% Item.count %])))
+[% ELSE -%]
+        if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %])))
+[% END -%]
+        {
+            errorStream.add((char *)"Failed to decode: [% Item.fieldName %]\n");
+            return false;
+        }
+[% IF Item.validationPresent == "y" -%]
+        if (!([% Item.validationRule %]))
+        {
+            errorStream.add((char *)"Data validation failure : [% Item.fieldName %]\n");
+            return false; //TODO need to add validations
+        }
+[% END -%]
+[% END -%]
+[% IF Item.presence == "optional" -%]
+        data.[% Item.fieldName %]Present = true;
+[% END -%]
+    }
+[% ELSE -%]
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+    data.[% Item.fieldName %] = buffer.readBits([% Item.fieldSize %]);
+    // confirm that we are not reading beyond the IE boundary
+    if (buffer.getCurrentIndex() > ieBoundary)
+    {
+        errorStream.add((char *)"Attempt to read beyond IE boundary: [% Item.fieldName %]\n");
+        return false;
+    }
+[% ELSE %]
+    buffer.read[% Item.fieldType %](data.[% Item.fieldName %]);
+    if (buffer.getCurrentIndex() > ieBoundary)
+    {
+        errorStream.add((char *)"Attempt to read beyond IE boundary: [% Item.fieldName %]\n");
+        return false;
+    }
+[% END -%]
+[% IF Item.validationPresent == "y" -%]
+    if (!([% Item.validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure : [% Item.fieldName %]\n");
+        return false; //TODO need to add validations
+    }
+[% END -%]
+[% ELSE -%]
+[% IF Item.length == "lengthLeft" -%]
+    lengthLeft = ieBoundary - buffer.getCurrentIndex();
+[% END -%]
+[% IF Item.arrayType == "y" -%]
+    if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %], [% Item.count %])))
+[% ELSE -%]
+    if (!(DataTypeCodecUtils::decode[% Item.fieldType %](buffer, data.[% Item.fieldName %], [% Item.length %])))
+[% END -%]
+    {
+        errorStream.add((char *)"Failed to decode: [% Item.fieldName %]\n");
+        return false;
+    }
+[% IF Item.validationPresent == "y" -%]
+    if (!([% Item.validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure : [% Item.fieldName %]\n");
+        return false; //TODO need to add validations
+    }
+[% END -%]
+[% END -%]
+[% IF Item.presence == "optional" -%]
+    data.[% Item.fieldName %]Present = true;
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+[% IF validationPresent == "y" -%]
+    if (!([% validationRule %]))
+    {
+        errorStream.add((char *)"Data validation failure at IE: [% tempdata.className %]\n");
+        return false;
+    }
+[% END -%]
+
+    // The IE is decoded now. The buffer index should be pointing to the 
+    // IE Boundary. If not, we have some more data left for the IE which we don't know
+    // how to decode
+    if (ieBoundary == buffer.getCurrentIndex())
+    {
+        return true;
+    }
+    else
+    {
+        errorStream.add((char *)"Unable to decode IE [% tempdata.className %]\n");
+        return false;
+    }
+}
+void [% tempdata.className %]::display[% tempdata.className %]_v([% tempdata.className %]Data const &data, Debug &stream)
+{
+    stream.incrIndent();
+    stream.add((char *)"[% tempdata.className %]Data:");
+    stream.incrIndent();
+    stream.endOfLine();
+[% FOREACH Item IN tempdata.sequence -%]
+[% IF Item.skipType != "y" -%]
+  
+[% IF Item.presence == "optional" -%]  
+    if (data.[% Item.fieldName %]Present)
+    {
+[% IF Item.encodeConditional == "y" -%]
+        if ([% Item.encodeCondition %])
+        {
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+            stream.add((char *) "[% Item.fieldName %]: "); 
+            stream.add((Uint8)data.[% Item.fieldName %]);
+            stream.endOfLine();
+[% ELSE -%]
+            stream.add((char *)"[% Item.fieldName %]: ");
+            stream.add(data.[% Item.fieldName %]);
+            stream.endOfLine();
+[% END -%]
+[% ELSE -%]
+            stream.add((char *)"[% Item.fieldName %]:");
+            stream.endOfLine();
+            DataTypeCodecUtils::display[% Item.fieldType %]_v(data.[% Item.fieldName %], stream);
+[% END -%]
+        }
+    }
+[% ELSE -%] 
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+        stream.add((char *) "[% Item.fieldName %]: "); 
+        stream.add((Uint8)data.[% Item.fieldName %]);
+        stream.endOfLine();
+[% ELSE -%]
+        stream.add((char *)"[% Item.fieldName %]: ");
+        stream.add(data.[% Item.fieldName %]);
+        stream.endOfLine();
+[% END -%]
+[% ELSE -%]
+        stream.add((char *)"[% Item.fieldName %]:");
+        stream.endOfLine();
+        DataTypeCodecUtils::display[% Item.fieldType %]_v(data.[% Item.fieldName %], stream);
+[% END -%]
+    }   
+[% END -%]
+[% ELSE -%]
+[% IF Item.encodeConditional == "y" -%]
+    if ([% Item.encodeCondition %])
+    {
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+        stream.add( (char *)"[% Item.fieldName %]: "); 
+        stream.add((Uint8)data.[% Item.fieldName %]);
+        stream.endOfLine();
+[% ELSE -%]
+        stream.add((char *)"[% Item.fieldName %]: ");
+        stream.add(data.[% Item.fieldName %]);
+        stream.endOfLine();
+[% END -%]
+[% ELSE -%]
+        stream.add((char *)"[% Item.fieldName %]:");
+        stream.endOfLine();
+        DataTypeCodecUtils::display[% Item.fieldType %]_v(data.[% Item.fieldName %], stream);
+[% END -%]
+    }
+[% ELSE -%] 
+[% IF Item.leafType == "y" -%]
+[% IF Item.bitField == "y" -%]
+    stream.add( (char *)"[% Item.fieldName %]: "); 
+    stream.add((Uint8)data.[% Item.fieldName %]);
+    stream.endOfLine();
+[% ELSE -%]
+    stream.add((char *)"[% Item.fieldName %]: ");
+    stream.add(data.[% Item.fieldName %]);
+    stream.endOfLine();
+[% END -%]
+[% ELSE -%]
+    stream.add((char *)"[% Item.fieldName %]:");
+    stream.endOfLine();
+    DataTypeCodecUtils::display[% Item.fieldType %]_v(data.[% Item.fieldName %], stream);
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+[% END -%]
+    stream.decrIndent();
+    stream.decrIndent();
+}
diff --git a/scripts/GtpV2StackCodeGen/tts/ietemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/ietemplate.h.tt
new file mode 100644
index 0000000..0dafcd2
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/ietemplate.h.tt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/ietemplate.h.tt>
+ ******************************************************************************/
+#ifndef [% tempdata.classNameUC %]_H_
+#define [% tempdata.classNameUC %]_H_
+
+#include "manual/gtpV2Ie.h"
+
+
+
+class [% tempdata.className %]: public GtpV2Ie {
+public:
+    [% tempdata.className %]();
+    virtual ~[% tempdata.className %]();
+
+    bool encode[% tempdata.className %](MsgBuffer &buffer,
+                 [% tempdata.className %]Data const &data);
+    bool decode[% tempdata.className %](MsgBuffer &buffer,
+                 [% tempdata.className %]Data &data, Uint16 length);
+    void display[% tempdata.className %]_v([% tempdata.className %]Data const &data,
+                 Debug &stream);
+};
+
+#endif /* [% tempdata.classNameUC %]_H_ */
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/makefiletemplate.tt b/scripts/GtpV2StackCodeGen/tts/makefiletemplate.tt
new file mode 100644
index 0000000..63e4c88
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/makefiletemplate.tt
@@ -0,0 +1,51 @@
+#
+# Copyright 2019-present, Infosys Limited.
+#
+# Licensed 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.
+
+include ../../Makefile.common
+
+gtpV2CodecOBJDIR := $(OBJDIR)/gtpV2Codec/
+
+gtpV2CodecLIB := $(LIBDIR)/libgtpV2Codec.so
+
+[% FOREACH lib IN makefiledata.libList -%]
+gtpV2CodecOBJS := $(addprefix $(gtpV2CodecOBJDIR), \
+[% FOREACH file IN lib.fileList -%]
+	[% file.objFile -%] \
+[% END -%]
+	ieClasses/manual/dataTypeCodecUtils_manual.o \
+	gtpV2StackWrappers.o )
+[% END -%]
+all :  $(gtpV2CodecLIB)
+
+.PHONY : all
+
+$(gtpV2CodecLIB) : $(gtpV2CodecOBJS)
+	mkdir -p $(LIBDIR)
+	$(CC) $(CFLAGS) -shared -o $(gtpV2CodecLIB) $(gtpV2CodecOBJS)
+
+$(gtpV2CodecOBJS) : $(OBJDIR)/gtpV2Codec/%.o : %.cpp
+	echo "$@ from $< "
+	mkdir -p $(gtpV2CodecOBJDIR)/ieClasses/manual
+	mkdir -p $(gtpV2CodecOBJDIR)/msgClasses/manual
+	$(CC) $(CFLAGS) $(INC_DIRS) -fPIC -c $< -o $@
+
+install:
+	mkdir -p $(TOPDIR)/target/lib
+	cp -rf  $(gtpV2CodecLIB) $(TOPDIR)/target/lib
+
+clean :
+	rm -rf $(gtpV2CodecLIB)
+	rm -rf $(gtpV2CodecOBJDIR)
+
+.PHONY : clean
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/msgDataTypetemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/msgDataTypetemplate.h.tt
new file mode 100644
index 0000000..0bccf65
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/msgDataTypetemplate.h.tt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */ 
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/msgDataTypetemplate.h.tt>
+ ******************************************************************************/
+#ifndef GTPV2MSGDATATYPES_H_
+#define GTPV2MSGDATATYPES_H_
+
+#include "../../gtpV2Codec/ieClasses/gtpV2GrpIeDataTypes.h"
+#include "../../gtpV2Codec/ieClasses/gtpV2IeDataTypes.h"
+
+typedef struct
+{
+    Uint8 msgType;
+    Uint16 msgLength;
+    bool teidPresent;
+    Uint32 teid;
+    Uint32 sequenceNumber;
+}GtpV2MessageHeader;
+
+[% FOREACH msg IN tempdata.msgList -%]
+typedef struct
+{
+[% FOREACH ieData IN msg.ieDetails -%]
+[% IF ieData.iePresence != 'M' -%][% IF ieData.ieCardinality == 1 -%]
+    bool [% ieData.ieVarName %]IePresent;   
+[% END -%][% END -%]
+[% END -%]
+
+
+[% FOREACH ieData IN msg.ieDetails -%]
+[% IF ieData.ieCardinality != 1 -%]
+
+    Uint16 [% ieData.ieVarName %]Count;
+[% END -%]
+[% IF ieData.grouped == 'Yes'-%]
+[% IF ieData.ieCardinality != 1 -%]
+    [% ieData.grpIeInstClassName%]Data [% ieData.ieVarName%][[%ieData.ieCardinality%]];
+[% ELSE -%]
+    [% ieData.grpIeInstClassName%]Data [% ieData.ieVarName%];
+[% END -%]
+[% ELSE -%]
+    [% ieData.ieType%]IeData [% ieData.ieVarName%];
+[% END -%]
+[% END -%]
+}[% msg.msgDataName %];
+
+[% END -%]
+
+//Ie Type Constants
+[% FOREACH msg IN tempdata.msgTypeList -%]
+static const  Uint8  [% msg.msgDataType %] = [% msg.msgValue %];    
+[% END -%]
+
+
+#endif 
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/msgDecode.tt b/scripts/GtpV2StackCodeGen/tts/msgDecode.tt
new file mode 100644
index 0000000..bd96798
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/msgDecode.tt
@@ -0,0 +1,27 @@
+[% IF ieTypeData.ieCardinality == 1 -%][% IF ieTypeData.grouped == "Yes" -%]
+					[% ieTypeData.grpIeInstClassName %] groupedIeInstance =
+					dynamic_cast<
+					[% ieTypeData.grpIeInstClassName %]&>(ieObject.getGroupedIe(msgType, [% ieTypeData.instance %]));
+					rc = groupedIeInstance.decode[% ieTypeData.grpIeInstClassName %](buffer, data.[% ieTypeData.ieVarName %], ieHeader.length);
+[% ELSE -%]
+					rc = ieObject.decode[% ieTypeData.ieType %]Ie(buffer, data.[% ieTypeData.ieVarName %], ieHeader.length);
+[% END -%]
+[% ELSE -%]
+					// First check if we have enough space left to decode and store this instance
+                    if (data.[% ieTypeData.ieVarName %]Count == [% ieTypeData.ieCardinality %])
+                    {
+                        errorStream.add((char *)"More than [% ieTypeData.ieCardinality %] instances of [% ieTypeData.ieVarName %] received\n");
+                        return false;
+                    }
+[% IF ieTypeData.grouped == "Yes" -%]
+                    [% ieTypeData.grpIeInstClassName %] groupedIeInstance =
+                    dynamic_cast<
+                    [% ieTypeData.grpIeInstClassName %]&>(ieObject.getGroupedIe(msgType, [% ieTypeData.instance %]));
+                    rc = groupedIeInstance.decode[% ieTypeData.grpIeInstClassName %](buffer,
+                    data.[% ieTypeData.ieVarName %][data.[% ieTypeData.ieVarName %]Count], ieHeader.length);
+                    data.[% ieTypeData.ieVarName %]Count++; // TODO Count validation
+[% ELSE -%]
+					rc = ieObject.decode[% ieTypeData.ieType %]Ie(buffer, data.[% ieTypeData.ieVarName %][[% ieTypeData.ieVarName %]Count], ieHeader.length);
+					data.[% ieTypeData.ieVarName %]Count++; // TODO Count validation
+[% END -%]
+[% END -%]
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/msgEncode.tt b/scripts/GtpV2StackCodeGen/tts/msgEncode.tt
new file mode 100644
index 0000000..b1dcd54
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/msgEncode.tt
@@ -0,0 +1,63 @@
+[% IF ieData.ieCardinality == 1 -%]
+
+    // Encode the Ie Header
+    header.ieType = [% ieData.ieType %]IeType;
+    header.instance = [% ieData.instance %];
+    header.length = 0; // We will encode the IE first and then update the length
+    GtpV2Ie::encodeGtpV2IeHeader(buffer, header);
+    startIndex = buffer.getCurrentIndex(); 
+    [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+    dynamic_cast<
+    [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+[% IF ieData.grouped == 'Yes'-%]
+    [% ieData.grpIeInstClassName %] groupedIeInstance =
+    dynamic_cast<
+     [% ieData.grpIeInstClassName %]&>([% ieData.ieLocalVar %].getGroupedIe(msgType, [% ieData.instance %]));
+    rc = groupedIeInstance.encode[% ieData.grpIeInstClassName %](buffer, data.[% ieData.ieVarName %]);
+[% ELSE -%]
+    rc = [% ieData.ieLocalVar %].encode[% ieData.ieType %]Ie(buffer, data.[% ieData.ieVarName %]);
+[% END -%]
+    endIndex = buffer.getCurrentIndex();
+    length = endIndex - startIndex;
+
+    // encode the length value now
+    buffer.goToIndex(startIndex - 3);
+    buffer.writeUint16(length, false);
+    buffer.goToIndex(endIndex);
+[% ELSE -%]
+    // First validate if the applicatoin provided more than the expected cardinality
+    if (data.[% ieData.ieVarName %]Count > [% ieData.ieCardinality %])
+    {
+        errorStream.add((char *)"Number of entries of [% ieData.ieVarName %] exceeded\n");
+        errorStream.add((char *)"Expected count: [% ieData.ieCardinality %] Received count: ");
+        errorStream.add((char *)"data.[% ieData.ieVarName %]Count");
+        errorStream.endOfLine();
+        return false;
+    }
+    for (Uint8 i = 0; i < data.[% ieData.ieVarName %]Count; i++)
+    {
+        // Encode the Ie Header
+        header.ieType = [% ieData.ieType %]IeType;
+        header.instance = [% ieData.instance %];
+        header.length = 0; // We will encode the IE first and then update the length
+        GtpV2Ie::encodeGtpV2IeHeader(buffer, header);
+        startIndex = buffer.getCurrentIndex(); 
+        [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+        dynamic_cast<
+        [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().
+        getIeObject([% ieData.ieType %]IeType));
+[% IF ieData.grouped == 'Yes'-%]
+        [% ieData.grpIeInstClassName %] groupedIeInstance = dynamic_cast<[% ieData.grpIeInstClassName %]&>([% ieData.ieLocalVar %].getGroupedIe(msgType, [% ieData.instance %]));
+        rc = groupedIeInstance.encode[% ieData.grpIeInstClassName %](buffer, data.[% ieData.ieVarName %][i]);
+[% ELSE -%]
+        rc = [% ieData.ieLocalVar %].encode[% ieData.ieType %]Ie(buffer, data.[% ieData.ieVarName %][i]);
+[% END -%]
+        endIndex = buffer.getCurrentIndex();
+        length = endIndex - startIndex;
+
+        // encode the length value now
+        buffer.goToIndex(startIndex - 3);
+        buffer.writeUint16(length, false);
+        buffer.goToIndex(endIndex);
+    }
+[% END -%]
diff --git a/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.cpp.tt
new file mode 100644
index 0000000..d21197e
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.cpp.tt
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */
+ 
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.cpp.tt>
+ ******************************************************************************/ 
+
+#include "gtpV2MsgFactory.h"
+[% FOREACH msg IN tempdata.msgList -%]
+#include "[% msg.msgFileName %].h"
+[% END -%]
+
+static GtpV2MsgFactory gtpV2MsgFactory;
+
+GtpV2MsgFactory::GtpV2MsgFactory() 
+{
+    //Create Message Objects
+        
+[% FOREACH msg IN tempdata.msgList -%]
+    [% msg.className %]* [% msg.msgFileName %]_p = new ([% msg.className %]);
+    msgObjectContainer.insert(std::pair<Uint8, GtpV2Message*>([% msg.className %]Type, [% msg.msgFileName %]_p));
+
+[% END -%]
+
+}
+
+GtpV2MsgFactory::~GtpV2MsgFactory() {
+    // TODO clean up the allocated memory for message objects
+}
+
+GtpV2MsgFactory& GtpV2MsgFactory::getInstance()
+{
+    static GtpV2MsgFactory gtpV2MsgFactory;
+    return gtpV2MsgFactory;
+}
+
+GtpV2Message& GtpV2MsgFactory::getMsgObject(Uint8 msgType)
+{
+    std::map<Uint8, GtpV2Message*>::iterator it;
+    it = msgObjectContainer.find(msgType);
+    return *(it->second);
+}
diff --git a/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.h.tt
new file mode 100644
index 0000000..e2546b2
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.h.tt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */ 
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/msgfactorytemplate.h.tt>
+ ******************************************************************************/
+#ifndef GTPV2MSGFACTORY_H_
+#define GTPV2MSGFACTORY_H_
+
+#include <map>
+#include "manual/gtpV2Message.h"
+
+class GtpV2MsgFactory {
+public:
+    GtpV2MsgFactory();
+    virtual ~GtpV2MsgFactory();
+
+    static GtpV2MsgFactory& getInstance();
+    GtpV2Message& getMsgObject(Uint8 msgType);
+
+private:
+
+    map<Uint8, GtpV2Message*> msgObjectContainer;
+
+};
+
+
+#endif /* GTPV2MSGFACTORY_H_ */
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/msgtemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/msgtemplate.cpp.tt
new file mode 100644
index 0000000..ceef7ae
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/msgtemplate.cpp.tt
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */
+
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/msgtemplate.cpp.tt>
+ ******************************************************************************/ 
+
+#include "[% tempdata.fileName %].h"
+#include "../ieClasses/manual/gtpV2Ie.h"
+#include "../ieClasses/gtpV2IeFactory.h"
+[% FOREACH ieData IN tempdata.ieList -%]
+#include "../ieClasses/[% ieData.ieFileName %].h"
+[% IF ieData.grouped == 'Yes'-%]
+#include "../ieClasses/[% ieData.grpIeInstFileName %].h"
+[% END -%]
+[% END -%]
+
+[% tempdata.msgClassName %]::[% tempdata.msgClassName %]()
+{
+    msgType = [% tempdata.msgClassName %]Type;
+[% PROCESS MandIeList %]
+}
+
+[% tempdata.msgClassName %]::~[% tempdata.msgClassName %]()
+{
+
+}
+
+bool [% tempdata.msgClassName %]::encode[% tempdata.msgClassName %](MsgBuffer &buffer,
+                        [% tempdata.msgClassName %]Data
+							const &data)
+{
+    bool rc = false;
+    GtpV2IeHeader header;
+    Uint16 startIndex = 0;
+    Uint16 endIndex = 0;
+    Uint16 length = 0;
+[% FOREACH ieData IN tempdata.ieList -%]
+
+[% IF ieData.iePresence != 'M' -%][% IF ieData.ieCardinality == 1 -%]
+    if (data.[% ieData.ieVarName %]IePresent)
+    {
+        [% INCLUDE tts/msgEncode.tt FILTER indent%]
+        if (!(rc))
+        { 
+            errorStream.add((char *)"Failed to encode IE: [% ieData.ieVarName %]\n");
+            return false;
+        }
+    }
+[% ELSE -%]
+    [% INCLUDE tts/msgEncode.tt %]
+    if (!(rc))
+    { 
+        errorStream.add((char *)"Failed to encode IE: [% ieData.ieVarName %]\n");
+        return false;
+    }
+[% END -%]
+[% ELSE -%]
+    [% INCLUDE tts/msgEncode.tt %]
+    if (!(rc))
+    { 
+        errorStream.add((char *)"Failed to encode IE: [% ieData.ieVarName %]\n");
+        return false;
+    }
+[% END -%]
+[% END -%]
+    return rc;
+
+}
+
+bool [% tempdata.msgClassName %]::decode[% tempdata.msgClassName %](MsgBuffer &buffer,
+ [% tempdata.msgClassName %]Data 
+ &data, Uint16 length)
+{
+
+    bool rc = false;
+    GtpV2IeHeader ieHeader;
+  
+    set<Uint16> mandatoryIeLocalList = mandatoryIeSet;
+    while (buffer.lengthLeft() > IE_HEADER_SIZE)
+    {
+        GtpV2Ie::decodeGtpV2IeHeader(buffer, ieHeader);
+        if (ieHeader.length > buffer.lengthLeft())
+        {
+            // We do not have enough bytes left in the message for this IE
+            errorStream.add((char *)"IE Length exceeds beyond message boundary\n");
+            errorStream.add((char *)"  Offending IE Type: ");
+            errorStream.add(ieHeader.ieType);
+            errorStream.add((char *)"\n  Ie Length in Header: ");
+            errorStream.add(ieHeader.length);
+            errorStream.add((char *)"\n  Bytes left in message: ");
+            errorStream.add(buffer.lengthLeft());
+            errorStream.endOfLine();
+            return false;
+        }
+
+        switch (ieHeader.ieType){
+[% FOREACH ieTypeEntry IN tempdata.ieTypeList -%]
+     
+            case [% ieTypeEntry %]IeType:
+            {
+                [% ieTypeEntry %]Ie ieObject =
+                dynamic_cast<
+                [% ieTypeEntry %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieTypeEntry %]IeType));
+[% SET first = 1 -%]
+[% FOREACH ieTypeData IN tempdata.ieList -%]
+[% IF ieTypeData.ieType == ieTypeEntry -%] 
+[% IF first == 1 -%]
+[% SET first = 0 %]
+                if(ieHeader.instance == [% ieTypeData.instance %])
+[% ELSE -%]
+                else if(ieHeader.instance == [% ieTypeData.instance %])
+[% END -%]
+                {
+[% INCLUDE tts/msgDecode.tt %]
+[% IF ieTypeData.ieCardinality == 1 -%][% IF ieTypeData.iePresence != "M" -%]
+                    data.[% ieTypeData.ieVarName %]IePresent = true;
+[% END -%][% END -%]
+                    if (!(rc))
+                    {
+                        errorStream.add((char *)"Failed to decode IE: [% ieTypeData.ieVarName %]\n");
+                        return false;
+                    }
+                }
+[% END %][% END %]
+                else
+                {
+                    // Unknown IE instance print error
+                    errorStream.add((char *)"Unknown IE Type: ");
+                    errorStream.add(ieHeader.ieType);
+                    errorStream.endOfLine();
+                    buffer.skipBytes(ieHeader.length);
+                }
+                break;
+            }
+[% END %]
+            default:
+            {
+                // Unknown IE print error
+                errorStream.add((char *)"Unknown IE Type: ");
+                errorStream.add(ieHeader.ieType);
+                errorStream.endOfLine();
+                buffer.skipBytes(ieHeader.length);
+            }
+        }
+    }
+    return rc; // TODO validations
+}
+
+void [% tempdata.msgClassName %]::
+display[% tempdata.msgClassName %]Data_v([% tempdata.msgClassName %]Data const &data, Debug &stream)
+{
+    stream.incrIndent();
+    stream.add((char *)"[% tempdata.msgClassName %]:");
+    stream.endOfLine();
+    stream.incrIndent();
+    
+    [%- flag = 0 -%]
+    
+    
+[% FOREACH ieData IN tempdata.ieList -%]
+[% IF ieData.ieCardinality != 1 -%]
+[%- IF flag == 0 %]
+    Uint8 displayCount;
+    
+[%- flag = 1 %]
+[% END -%][% END -%]
+[% IF ieData.iePresence != 'M' -%][% IF ieData.ieCardinality == 1 -%]
+    if (data.[% ieData.ieVarName %]IePresent)
+    {
+
+
+        stream.add((char *)"IE - [% ieData.ieVarName %]:");
+        stream.endOfLine();
+        [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+        dynamic_cast<
+        [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+    [% PROCESS ieDisplay_grp %]
+    }
+[% ELSE -%]
+    displayCount = data.[% ieData.ieVarName %]Count;
+    if (displayCount > [% ieData.ieCardinality %])
+    {
+        stream.add((char *)"Invalid data more than [% ieData.ieCardinality %] instances");
+        stream.endOfLine();
+        stream.add((char *)"Displaying only [% ieData.ieCardinality %]");
+        stream.endOfLine();
+        displayCount = [% ieData.ieCardinality %];
+    }
+    for (Uint8 i = 0; i < displayCount; i++)
+    {
+        stream.add((char *)"IE -  [% ieData.ieVarName %]:");
+        stream.endOfLine();
+        [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+        dynamic_cast<
+        [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+        [% PROCESS ieDisplay_grp -%]
+    }
+
+    
+
+    
+[% END -%]
+[% ELSE -%]
+[% IF ieData.ieCardinality == 1 -%]
+        stream.add((char *)"IE - [% ieData.ieVarName %]:");
+        stream.endOfLine();
+        [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+        dynamic_cast<
+        [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+    [% PROCESS ieDisplay_grp %]
+[% ELSE -%]
+    displayCount = data.[% ieData.ieVarName %]Count;
+    if (displayCount > [% ieData.ieCardinality %])
+    {
+        stream.add((char *)"Invalid data more than [% ieData.ieCardinality %] instances");
+        stream.endOfLine();
+        stream.add((char *)"Displaying only [% ieData.ieCardinality %]");
+        stream.endOfLine();
+        displayCount = [% ieData.ieCardinality %];
+    }
+    for (Uint8 i = 0; i < displayCount; i++)
+    {
+        stream.add((char *)"IE -  [% ieData.ieVarName %]:");
+        stream.endOfLine();
+        [% ieData.ieType %]Ie [% ieData.ieLocalVar %]=
+        dynamic_cast<
+        [% ieData.ieType %]Ie&>(GtpV2IeFactory::getInstance().getIeObject([% ieData.ieType %]IeType));
+[% PROCESS ieDisplay_grp %]
+    }
+[% END -%]            
+[% END -%]
+[% END -%]
+
+    stream.decrIndent();
+    stream.decrIndent();
+}
+
+[% BLOCK ieDisplay_grp -%]
+[% IF ieData.grouped == "Yes" -%]
+        [% ieData.grpIeInstClassName %] groupedIeInstance =
+        dynamic_cast<
+        [% ieData.grpIeInstClassName %]&>([% ieData.ieLocalVar %].getGroupedIe(msgType, [% ieData.instance %]));
+        groupedIeInstance.display[% ieData.grpIeInstClassName %]Data_v(data.[% ieData.ieVarName %][% PROCESS cardinalIndex %], stream);
+[% ELSE -%]
+    [% ieData.ieLocalVar %].display[% ieData.ieType %]Ie_v(data.[% ieData.ieVarName %][% PROCESS cardinalIndex %], stream);
+[% END -%]
+[% END -%]
+
+[% BLOCK cardinalIndex -%]
+[% IF ieData.ieCardinality != 1 %][i][% END -%]
+[% END -%]
+[% BLOCK MandIeList -%]
+[% SET first = 1 -%]
+[% FOREACH ieData IN tempdata.ieList -%]
+[% IF ieData.iePresence == 'M' -%]
+[% IF first == 1 -%]
+    Uint16 mandIe;
+[% SET first = 0 -%]
+[% END -%]
+    mandIe = [% ieData.ieType %]IeType;
+    mandIe = (mandIe << 8) | [% ieData.instance %]; // [% ieData.ieVarName %]
+    mandatoryIeSet.insert(mandIe);
+[%- END -%]
+[% END -%]
+[% END -%]
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/msgtemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/msgtemplate.h.tt
new file mode 100644
index 0000000..949d03f
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/msgtemplate.h.tt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/msgtemplate.h.tt>
+ ******************************************************************************/
+#ifndef [% tempdata.classNameUC %]_H_
+#define [% tempdata.classNameUC %]_H_
+
+#include <set>
+#include "manual/gtpV2Message.h"
+#include <msgBuffer.h>
+#include <debug.h>
+#include "gtpV2MsgDataTypes.h"
+
+
+class [% tempdata.msgClassName %]:public GtpV2Message
+{
+public:
+    [% tempdata.msgClassName %]();
+    virtual ~[% tempdata.msgClassName %]();
+    bool encode[% tempdata.msgClassName %](MsgBuffer &buffer, [% tempdata.msgClassName %]Data const &data);
+
+    bool decode[% tempdata.msgClassName %] (MsgBuffer &buffer, [% tempdata.msgClassName %]Data& data, Uint16 length);
+
+    void display[% tempdata.msgClassName %]Data_v([% tempdata.msgClassName %]Data const &data, Debug &stream);
+
+private:
+    set <Uint16> mandatoryIeSet;
+};
+
+#endif
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/tts/stacktemplate.cpp.tt b/scripts/GtpV2StackCodeGen/tts/stacktemplate.cpp.tt
new file mode 100644
index 0000000..a9d511c
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/stacktemplate.cpp.tt
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2019-present Infosys Limited  
+ *   
+ * SPDX-License-Identifier: Apache-2.0    
+ */
+ 
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/stacktemplate.cpp.tt>
+ ******************************************************************************/
+#include <cstring>
+#include <stdint.h>
+#include "gtpV2Stack.h"
+#include "msgClasses/gtpV2MsgFactory.h"
+#include "msgClasses/manual/gtpV2Message.h"
+[% FOREACH msg IN tempdata.msgList -%]
+#include "msgClasses/[% msg.msgFileName %].h"
+[% END -%]
+
+cmn::utils::Debug errorStream;
+
+GtpV2Stack::GtpV2Stack ()
+{
+    // TODO Auto-generated constructor stub
+
+}
+
+GtpV2Stack::~GtpV2Stack ()
+{
+    // TODO Auto-generated destructor stub
+}
+
+bool
+GtpV2Stack::encodeMessage (GtpV2MessageHeader & msgHeader, 
+			   MsgBuffer & buffer, void *data_p)
+{
+
+    //Clear the global errorStream
+    errorStream.clearStream ();
+    bool rc = false;
+    GtpV2Message & msg =
+    GtpV2MsgFactory::getInstance ().getMsgObject (msgHeader.msgType);
+
+	uint16_t gtpHeaderStartIdx = buffer.getCurrentIndex();
+    // Encode the header
+    GtpV2Message::encodeHeader (buffer, msgHeader);
+
+    Uint16 startIndex = buffer.getCurrentIndex();
+
+    switch (msgHeader.msgType)
+    {
+[% FOREACH msg IN tempdata.msgList -%]
+        case [% msg.className %]Type:
+        {
+            if (data_p != NULL)
+            {
+                rc =
+               dynamic_cast<
+               [% msg.className %] & >(msg).
+               encode[% msg.className %](buffer,
+    			     *(([% msg.className %]Data *)
+        			     data_p));
+            }
+            else
+            { 
+                // Application has filled the data structure provided by the stack
+                rc = 
+                dynamic_cast<
+                [% msg.className %] & >(msg).
+                encode[% msg.className %] (buffer,
+                            [% msg.dataMember %]);
+            }
+            break;
+        }
+[% END -%]
+    }
+
+    Uint16 endIndex = buffer.getCurrentIndex ();
+
+    Uint16 messageLength = (endIndex - startIndex)+8;
+
+    buffer.goToIndex (gtpHeaderStartIdx  + 2); // 2 is where length is encoded in a gtp message TODO remove hardcoding
+    buffer.writeUint16 (messageLength, false);
+    buffer.goToIndex (endIndex);
+    return rc;
+}
+
+bool
+GtpV2Stack::decodeGtpMessageHeader(GtpV2MessageHeader& msgHeader, MsgBuffer& buffer)
+{
+	 return GtpV2Message::decodeHeader (buffer, msgHeader);
+}
+
+
+bool
+GtpV2Stack::decodeMessage (GtpV2MessageHeader& msgHeader, 
+                MsgBuffer& buffer,void* data_p)
+{
+    errorStream.clearStream();
+    // First decode the message header
+    bool rc = false;
+      
+    
+    
+    Uint16 msgDataLength = msgHeader.msgLength;
+    
+    if (msgHeader.teidPresent)
+    {
+        msgDataLength = msgDataLength - 8; //teid and sequence number
+    }
+    else
+    {
+        msgDataLength = msgDataLength - 4; //only sequence number
+    }
+  
+    // Validate the length before proceeding
+    if (msgDataLength != buffer.lengthLeft() )
+    {
+        // Encoded message length does not match the number of bytes left in the message
+        errorStream.add ((char *)"Message length does not match bytes in buffer\n");
+        errorStream.add ((char *)"Computed Message length: ");
+        errorStream.add (msgDataLength);
+        errorStream.add ((char *)"  Bytes Left in buffer: ");
+        errorStream.add (buffer.lengthLeft());
+        errorStream.endOfLine ();
+        return false;
+    }
+
+    GtpV2Message& msg = 
+    GtpV2MsgFactory::getInstance ().getMsgObject (msgHeader.msgType);
+
+    switch (msgHeader.msgType){
+[% FOREACH msg IN tempdata.msgList -%]
+        case [% msg.className %]Type:
+        {
+            if (data_p != NULL)
+            {
+                rc =
+                dynamic_cast<
+                [% msg.className %] & >(msg).
+                decode[% msg.className %](buffer,
+                            *([% msg.className %]Data*)
+                             data_p, msgDataLength);
+            }
+            else
+            { 
+                // Application wants to use the data structure provided by the stack
+                // let us first clear any data present in the internal data structure
+                memset (&[% msg.dataMember %], 0,
+                sizeof ([% msg.className %]Data));
+                rc =
+                dynamic_cast<
+                [% msg.className %] & >(msg).
+                decode[% msg.className %](buffer,
+                            [% msg.dataMember %],
+                            msgDataLength);
+            }
+            break;
+        }
+[% END -%]
+    }
+    return rc;
+}
+
+void 
+GtpV2Stack::display_v(Uint8 msgType, Debug& stream, void* data_p)
+{
+    // Display the messageType
+    stream.add ((char *)"MessageType: ");
+    stream.add (msgType);
+    stream.endOfLine ();
+      
+    GtpV2Message& msg = GtpV2MsgFactory::getInstance ().getMsgObject (msgType);
+
+    switch (msgType){
+[% FOREACH msg IN tempdata.msgList -%]
+        case [% msg.className %]Type:
+        {
+            stream.add ((char *)"Message: [% msg.className %]");
+            stream.endOfLine ();
+            if (data_p != NULL)
+            {
+            dynamic_cast<
+            [% msg.className %] & >(msg).
+            display[% msg.className %]Data_v (*
+                        (([% msg.className %]Data*) data_p), stream);
+            }
+            else
+            {
+            // Application wants to use the data structure provided by the stack
+            dynamic_cast<
+            [% msg.className %] & >(msg).
+            display[% msg.className %]Data_v
+                        ([% msg.dataMember %], stream);
+            }
+           break;
+        }
+[% END -%]
+    }
+}
diff --git a/scripts/GtpV2StackCodeGen/tts/stacktemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/stacktemplate.h.tt
new file mode 100644
index 0000000..044c57a
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/stacktemplate.h.tt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */ 
+/******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/stacktemplate.h.tt>
+ ******************************************************************************/
+#ifndef GTPV2STACK_H_
+#define GTPV2STACK_H_
+
+#include <sstream>
+#include <basicTypes.h>
+#include <msgBuffer.h>
+#include "msgClasses/gtpV2MsgDataTypes.h"
+
+class GtpV2Stack {
+public:
+    GtpV2Stack();
+    virtual ~GtpV2Stack();
+
+    // Public datastructures that hold decoded data or data to be encoded
+[% FOREACH msg IN tempdata.msgList -%]
+    [% msg.className %]Data [% msg.dataMember %];
+[% END -%]
+
+    bool encodeMessage(GtpV2MessageHeader& msgHeader, MsgBuffer& buffer,
+                 void* data_p = NULL);
+	bool decodeGtpMessageHeader(GtpV2MessageHeader& msgHeader, MsgBuffer& buffer);
+    bool decodeMessage(GtpV2MessageHeader& msgHeader, MsgBuffer& buffer,
+                 void* data_p = NULL);
+    void display_v(Uint8 msgType, Debug& stream, void* data_p = NULL);
+};
+
+#endif /* GTPV2STACK_H_ */
diff --git a/scripts/GtpV2StackCodeGen/tts/v2DataTypetemplate.h.tt b/scripts/GtpV2StackCodeGen/tts/v2DataTypetemplate.h.tt
new file mode 100644
index 0000000..b3d982d
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/tts/v2DataTypetemplate.h.tt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019-present, Infosys Limited.
+ *
+ * Licensed 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.
+ */
+ /******************************************************************************
+ *
+ * This is an auto generated file.
+ * Please do not edit this file.
+ * All edits to be made through template source file
+ * <TOP-DIR/scripts/GtpV2StackCodeGen/tts/v2DataTypetemplate.h.tt>
+ ******************************************************************************/
+#ifndef GTPV2DATATYPES_H_
+#define GTPV2DATATYPES_H_
+#include <basicTypes.h>
+
+[%- arrayDataTypesList = [] -%]
+[%- FOREACH data IN tempdata.DataTypeListAuto -%]
+    [%- FOREACH seq IN data.sequence -%]
+        [%- IF seq.skipType !='y' -%]
+            [%- FOREACH arrayItem IN tempdata.arrayTypeList -%]
+                [%- IF seq.fieldType == arrayItem.typeName -%]
+                    [% arrayDataTypesList.push(arrayItem.typeName) -%]
+                [% END -%]
+            [% END -%]
+        [% END -%]
+    [% END -%]
+[% END -%]
+[%- arrayDataTypesList = arrayDataTypesList.unique -%]
+[%- FOREACH data IN tempdata.arrayTypeList -%]
+    [%- flag = 0 -%]
+    [%- FOREACH item IN arrayDataTypesList -%]
+        [%- IF item == data.typeName %]
+            [%- flag = 1 %]
+        [%- END -%]
+    [%- END -%]
+    [%- IF flag == 1 %]
+typedef struct
+{
+    Uint16 count;
+    [% data.subType %] values[[% data.arraySize %]];
+
+}[% data.typeName %];
+    [% END -%]
+[% END -%]
+
+[% FOREACH data IN tempdata.DataTypeListAuto -%]
+typedef struct
+{
+[% FOREACH seq IN data.sequence -%][% IF seq.skipType !='y' -%]
+    [% seq.fieldType %] [% seq.fieldName %];
+[% END -%][% END -%]
+}[% data.typeName %];
+
+[% END -%]
+
+[% FOREACH data IN tempdata.arrayTypeList -%]
+    [% flag = 0 -%]
+    [% FOREACH item IN arrayDataTypesList -%]
+        [% IF item == data.typeName %]
+            [% flag = 1 %]
+        [% END -%]
+    [% END -%]
+    [% IF flag == 0 %]
+typedef struct
+{
+    Uint16 count;
+    [% data.subType %] values[[% data.arraySize %]];
+
+}[% data.typeName %];
+    [% END -%]
+[% END -%]
+
+#endif 
\ No newline at end of file