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

Change-Id: Ie55032217232214ac8544ca76ea34335205329e4
diff --git a/scripts/GtpV2StackCodeGen/README.txt b/scripts/GtpV2StackCodeGen/README.txt
new file mode 100644
index 0000000..7958516
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/README.txt
@@ -0,0 +1,28 @@
+Requirements:
+1.Python3.6.
+2.Install the template-toolkit package.
+	a. pip3 install Template-Toolkit-Python or 
+	b. git clone https://github.com/lmr/Template-Toolkit-Python, and set the path of the package in the datatypeCodeGen.py,groupedIECodeGen.py,iECodeGen.py,msgCodeGen.py,xlUtils.py script [as argument in sys.path.append]
+
+Inputs:
+	1 Excel file with 4 spreadsheets:
+		Message Modeling ,IE Modeling,Grouped IE Modeling and DataType Modeling: Defines the message structure,IEs,Grouped IEs and Datatype of IEs for the GTP classes to be generated . 
+Output:
+	1.	IE Classes .cpp and header files. 
+	2.	Message Classes .cpp and header files.
+	3.	gtpV2stack .cpp and header files
+	4.	MakeFile
+
+
+Remove all existing generated Files:
+-Use below commands:
+	rm ../../src/gtpV2Codec/ieClasses/*.cpp ../../src/gtpV2Codec/ieClasses/*.h;
+	rm ../../src/gtpV2Codec/msgClasses/*.cpp ../../src/gtpV2Codec/msgClasses/*.h;
+	rm ../../src/gtpV2Codec/Makefile;
+Execution:
+-Run the below command:
+	python3 startCodeGen.py
+
+
+
+
diff --git a/scripts/GtpV2StackCodeGen/dataModel/prototypeV8.xlsx b/scripts/GtpV2StackCodeGen/dataModel/prototypeV8.xlsx
new file mode 100644
index 0000000..6b3d954
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/dataModel/prototypeV8.xlsx
Binary files differ
diff --git a/scripts/GtpV2StackCodeGen/datatypeCodeGen.py b/scripts/GtpV2StackCodeGen/datatypeCodeGen.py
new file mode 100644
index 0000000..81e48a9
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/datatypeCodeGen.py
@@ -0,0 +1,335 @@
+# Copyright 2019-present Infosys Limited     
+# SPDX-License-Identifier: Apache-2.0
+
+
+import re
+from template import Template
+import os
+from xlUtils import xlUtils,wb
+dataTypeData={}
+dataTypeData['arrayTypeList']=[]
+dataTypeData['DataTypeListAuto']=[]
+class GenerateDataTypeClass():
+    def __init__( self ):
+        self.templateDataTypes()  
+
+        
+    def templateDataTypes(self):
+        typeDataTemplate = GenerateDataTypeClass.dataTypeParser()
+        
+        templateData = dict()
+        sequenceList = []
+        dataTypeListAuto = []
+        arrayTypeInfoList = []
+        dataTypeListManual = []
+        templateData['className'] = 'DataTypeCodecUtils'
+        templateData['fileName'] = templateData['className'][0].lower()+templateData['className'][1:]
+        templateData['classNameUC'] = templateData['className'].upper()
+        
+        #building the dictionary obtained to a dict 'templateData'
+        #which is the input to template process 
+        for typeNames in typeDataTemplate['DataTypeList']:
+            myData = {}
+            sequenceList = []
+            
+            
+            myData['typeName'] = typeNames
+            for typeDetails in typeDataTemplate['typeDetails']:
+                if typeNames in typeDetails:
+                    myTypeData = typeDetails[typeNames]
+                   
+                    for varDetails in myTypeData['varDetails']:
+                     
+                        for key,value in varDetails.items():
+                            for en in myTypeData['encodeSeq']:
+                               
+                                mEncode = re.search('encode:(\w+):',en)
+                                mSkip = re.search('skip:(\d+):(\w+)',en)
+                                item = dict()
+                               
+                                if mSkip:
+                                    bitByte = mSkip.group(2)
+                                    skipValue = mSkip.group(1)
+                                    item['skipType'] = 'y'
+                                    item['bitByte'] = bitByte
+                                    item['skipValue'] = skipValue
+                                elif mEncode:
+                                    varName = mEncode.group(1)
+                                    if key == varName:
+                                        item['fieldName'] = varName
+                                        if value['bitLength'] != 0:
+                                            item['bitField'] = 'y'
+                                            item['fieldSize'] = value['bitLength']
+                                            item['leafType'] = 'y'
+                                        else:
+                                            item['fieldSize'] = value['byteLength']
+                                        if value['decodeCondition'] != '':
+                                            item['decodeConditional'] = 'y'
+                                            item['decodeCondition'] = value['decodeCondition']
+                                        if value['encodeCondition'] != '':
+                                            item['encodeConditional'] = 'y'
+                                            item['encodeCondition'] = value['encodeCondition']
+                                        if value['presence'] == 'optional':
+                                            item['presence'] = 'optional'
+                                        item['fieldType'] = value['varType']
+                                        mUint = re.search('^Uint(\d+)$',value['varType'])
+                                        if mUint or value['varType'] == 'bool':
+                                
+                                            item['leafType'] = 'y'
+                    
+                                        else:
+                                            if value['lengthStr'] == 'EOI' or value['lengthStr'] == '':
+                                                item['length'] = 'lengthLeft'
+                                            else:
+                                                item['length'] = value['lengthStr']
+                                        mArrayUint = re.search('^(\w+)Array(\d+)$',value['varType'])
+                                        if mArrayUint :
+                                
+                                            item['arrayType'] = 'y'
+                                            
+                                            item['count'] =0
+                                                
+                                        if value['validation'] != '':
+                    
+                                            item['validationPresent'] = 'y'
+                                            item['validationRule'] = value['validation']
+                    
+                                if item not in sequenceList and item!={}:
+                                    sequenceList.append(item)
+                                    
+               
+            
+            for arrayLists in typeDataTemplate['ArrayTypeList']:
+                arrayTypeInfo = {} 
+                
+                if typeNames in arrayLists:
+                       
+                    arrayType = arrayLists[typeNames]
+                    arrayTypeInfo['typeName'] = arrayType['arrayTypeName']
+                    arrayTypeInfo['subType'] = arrayType['arraySubType']
+                    mArraySubType = re.search('^Uint\d+$',arrayTypeInfo['subType'])
+                    if mArraySubType:
+                        arrayTypeInfo['leafType'] = 'y'
+                    
+                    arrayTypeInfoList.append(arrayTypeInfo)
+                        
+            for dataCodecManual in typeDataTemplate['DataTypeCodecList']:
+                if typeNames == dataCodecManual:
+                    dataTypeListManual.append(myData)
+                    
+            
+            
+            if sequenceList != []:
+                myData['sequence'] = sequenceList
+                dataTypeListAuto.append(myData)
+                
+          
+                   
+        templateData['arrayTypeList'] = arrayTypeInfoList
+        templateData['DataTypeListManual'] = dataTypeListManual
+        templateData['DataTypeListAuto'] = dataTypeListAuto  
+        
+        GenerateDataTypeClass.generateDataType(templateData) 
+        outputDir = '../../src/gtpV2Codec/ieClasses'  
+        ttFileNameCpp = 'tts/datatypetemplate.cpp.tt'
+        ttFileNameH = 'tts/datatypetemplate.h.tt'
+        xlUtils.templateProcess(templateData,ttFileNameCpp,ttFileNameH,outputDir,outputDir)
+       
+    #Parse the data from excel sheet 'DataType Modeling' 
+    #and build to a dict 'typeData'
+    def dataTypeParser():
+        
+        sheet = wb['DataType Modeling']
+        state = ''
+        typeData = {}
+        encodeSeq = []
+        varDetailList = []
+        dataTypeList = []
+        dataTypeCodecList = []
+        arrayTypeList = []
+        typeDataList = []
+        currentType = ''
+        currentDataType = ''
+        varType = ''
+        decodeCondition = ''
+        encodeCondition = ''
+        validation = ''
+        bitLength = 0
+        byteLength = 0
+        lengthStr = ''
+        presence = ''
+        dataType = {}
+        
+        for i in range(1,sheet.max_row+1):
+            cell_value_B = xlUtils.getCellValue(sheet,i,'B')
+            
+            # Search pattern for data definition start,end 
+            mDataDefineStartCodec = re.search('DataType Definition Start:(\w+):Codec\[Manual\]\s*$',str(cell_value_B))
+            mArrayDefine = re.search('ArrayTypes Definition:([\w\d]*)Array(\d+)',str(cell_value_B))
+            mDataDefineStart = re.search('DataType Definition Start:(\w+)',str(cell_value_B))
+            mDataDefineEnd = re.search('DataType Definition End:(\w+)',str(cell_value_B))
+            if mDataDefineStartCodec:
+                currentType = mDataDefineStartCodec.group(1)
+                currentDataType = currentType
+                dataTypeCodecList.append(currentDataType)
+                typeData['DataTypeCodecList'] = dataTypeCodecList
+                dataTypeList.append(currentDataType)
+                typeData['DataTypeList'] = dataTypeList
+                continue
+            
+            if mArrayDefine:
+                
+                arraySubType = mArrayDefine.group(1)
+                arrayCount = mArrayDefine.group(2)
+                arrayTypeName = arraySubType + 'Array' + arrayCount
+                typeData['ArrayTypeList'] = {}
+                typeData['ArrayTypeList'][arrayTypeName] = {}
+                typeData['ArrayTypeList'][arrayTypeName]['arrayTypeName'] = arrayTypeName
+                typeData['ArrayTypeList'][arrayTypeName]['arraySubType'] = arraySubType
+                typeData['ArrayTypeList'][arrayTypeName]['arrayCount'] = arrayCount
+                arrayTypeList.append(typeData['ArrayTypeList'])
+                typeData['ArrayTypeList'] = arrayTypeList
+                dataTypeList.append(arrayTypeName)
+                typeData['DataTypeList'] = dataTypeList
+                continue
+            
+            if mDataDefineStart:
+                currentType = mDataDefineStart.group(1)
+                currentDataType = currentType
+                
+                state = 'StartDetected'
+                dataTypeList.append(currentDataType)
+                typeData['DataTypeList'] = dataTypeList
+                typeData['typeDetails'] = {}
+                typeData['typeDetails'][currentDataType] = {}
+                dataType = typeData['typeDetails'][currentDataType]
+                typeData['typeDetails'][currentDataType]['typeName'] = currentType
+                typeDataList.append(typeData['typeDetails'])
+                typeData['typeDetails'] = typeDataList
+                
+            elif mDataDefineEnd:
+                state = 'EndDetected'
+               
+            elif state == 'StartDetected':
+                encodeSeq = []
+                varDetailList = []
+                state = 'TypeDefinitionStart'
+            elif state == 'TypeDefinitionStart':
+                (byteLength,lengthStr) = xlUtils.getByteLength(sheet,i)
+                
+                #for fields less than 1 bytelength
+                
+                if byteLength == 0:
+                   varList = []
+                   
+                   for j in map(chr, range( ord('D'), ord('L'))):
+                       field = xlUtils.getCellValue(sheet,i,j)
+                       bitLength = 0
+                       byteLength = 0
+                       if field != None:
+                           
+                           bitLength = xlUtils.getBitLength(sheet,i,j) 
+                           (varName,varType,encodeCondition,decodeCondition,validation,count) = xlUtils.extractField(field)
+                           
+                           if varType == '':
+                               varType = 'Uint8'
+                           if bitLength == 8:
+                               byteLength = 1
+                               bitLength = 0        
+                           if varName != 'Spare':
+                               varList.append(varName)
+                            
+                               dataType['varDetails'] = {}
+                               dataType['varDetails'][varName] = {}
+                               dataType['varDetails'][varName]['varType'] = varType
+                               dataType['varDetails'][varName]['decodeCondition'] = decodeCondition
+                               dataType['varDetails'][varName]['encodeCondition'] = encodeCondition
+                               dataType['varDetails'][varName]['validation'] = validation
+                               dataType['varDetails'][varName]['bitLength'] = bitLength
+                               dataType['varDetails'][varName]['byteLength'] = byteLength
+                               dataType['varDetails'][varName]['lengthStr'] = lengthStr
+                               dataType['varDetails'][varName]['presence'] = presence
+                               
+                               encStrBit = 'encode:' + varName + ':' + str(bitLength) + ':Bits'
+                               encodeSeq.append(encStrBit)
+                               dataType['encodeSeq'] = encodeSeq
+                               varDetailList.append(dataType['varDetails'])
+                               dataType['varDetails'] = varDetailList
+                               
+                               
+                               
+                               
+                           else:
+                               skipStrBit = 'skip:'+ str(bitLength) + ':Bits'
+                               encodeSeq.append(skipStrBit)
+                               dataType['encodeSeq'] = encodeSeq
+                               
+                #for fields of length 1 byte
+                else:
+                    varList = []
+                    
+                    field = sheet.cell(row=i, column=4).value
+                    (varName,varType,encodeCondition,decodeCondition,validation,count) = xlUtils.extractField(field)
+                    
+                    if varType == '':
+                        varType = xlUtils.lengthToType(byteLength)
+                
+                    if varName != 'Spare':
+                        varList.append(varName)
+                        
+                        
+                        dataType['varDetails'] = {}
+                        dataType['varDetails'][varName] = {}
+                        dataType['varDetails'][varName]['varType'] = varType
+                        dataType['varDetails'][varName]['decodeCondition'] = decodeCondition
+                        dataType['varDetails'][varName]['encodeCondition'] = encodeCondition
+                        dataType['varDetails'][varName]['validation'] = validation
+                        dataType['varDetails'][varName]['bitLength'] = bitLength
+                        dataType['varDetails'][varName]['byteLength'] = byteLength
+                        dataType['varDetails'][varName]['lengthStr'] = lengthStr
+                        bitLength = 0
+                        byteLength = 0
+                        
+                        if str(cell_value_B) == 'Yes':
+                             presence = 'optional'  
+                        dataType['varDetails'][varName]['presence'] = presence
+                        varDetailList.append(dataType['varDetails'])
+                        dataType['varDetails'] = varDetailList
+                        
+                        encStrByte = 'encode:' + varName + ':' + str(byteLength) + ':Bytes'
+                        encodeSeq.append(encStrByte)
+                        dataType['encodeSeq'] = encodeSeq
+                        
+                    else:
+                        skipStrByte = 'skip:'+ str(byteLength) + ':Bytes'
+                        encodeSeq.append(skipStrByte)
+                        dataType['encodeSeq'] = encodeSeq
+                        
+        return typeData    
+        
+    def generateDataType(templateData):
+        dataTypeInfo={}
+        dataTypeData['arrayTypeList']=[]
+        for dataType in templateData['arrayTypeList']:
+            dataTypeInfo={}
+            dataTypeInfo['typeName']=dataType['typeName']
+            dataTypeInfo['subType']=dataType['subType']
+            mtypeName = re.search('^(\w+)Array(\d+)$',dataTypeInfo['typeName'])
+            if mtypeName:
+                
+                dataTypeInfo['arraySize']=mtypeName.group(2)
+            dataTypeData['arrayTypeList'].append(dataTypeInfo)
+        dataTypeData['DataTypeListAuto']=templateData['DataTypeListAuto']
+        
+        
+        template = Template()
+        ttFileNamefactoryH = 'tts/v2DataTypetemplate.h.tt'
+        outputDir = '../../src/gtpV2Codec/ieClasses'
+        
+        if not os.path.exists(outputDir):
+            os.makedirs(outputDir)
+        outputFileName = 'gtpV2DataTypes.h'
+        template.__init__({'OUTPUT' : outputFileName, 'OUTPUT_PATH' : outputDir})
+        template.process(ttFileNamefactoryH, {'tempdata' : dataTypeData})
+        
+GenerateDataTypeClass()
diff --git a/scripts/GtpV2StackCodeGen/groupedIECodeGen.py b/scripts/GtpV2StackCodeGen/groupedIECodeGen.py
new file mode 100644
index 0000000..072ccc0
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/groupedIECodeGen.py
@@ -0,0 +1,271 @@
+# Copyright 2019-present Infosys Limited     
+# SPDX-License-Identifier: Apache-2.0
+
+
+import re
+import os
+
+from template import Template
+from xlUtils import xlUtils,wb
+templateData = {}
+templateData['instList']=[]
+grpIeDataTypeData={}
+grpIeDataTypeData['grpList']=[]
+grpIeDataTypeData['grpTypeList']=[]
+class GenerateGrpIeClass():
+    def __init__( self ):
+        
+        self.groupIEParser()
+    
+    def groupIEParser(self):
+        
+        
+        sheet = wb['Grouped IE Modeling']
+        state = ''
+        
+        data = {}
+        grpIeData = {}
+        currentGrpie = ''
+        currentMsg = ''
+        currentVar = ''
+        currentInstance = ''
+        currentInstanceValue = 0
+        grpIeList = []
+        ieDetailsList = []
+        ieList = []
+       
+        for i in range(1,sheet.max_row+1):
+            
+            cell_value_B = xlUtils.getCellValue(sheet,i,'B')
+            
+            mGroupedIeDefStart = re.search('Grouped IE Definition Start:(\w+):(\d+):(\w+):(\w+):Instance\[(\d+)]',str(cell_value_B))
+            mGroupedIeDefEnd = re.search('Grouped IE Definition End:(\w+):(\w+)',str(cell_value_B))
+            
+            if mGroupedIeDefStart:
+                
+                state = 'StartDetected'
+                currentGrpie = mGroupedIeDefStart.group(1)
+                currentMsg = mGroupedIeDefStart.group(4)
+                currentVar = mGroupedIeDefStart.group(3)
+                currentInstanceValue = mGroupedIeDefStart.group(5)
+                currentInstance = currentVar + 'In' + currentMsg
+                
+                if currentGrpie not in grpIeList:
+                     grpIeList.append(currentGrpie)
+                     data['grpIeList'] = grpIeList
+                data['grpIeDetails'] = {}
+                data['grpIeDetails'][currentGrpie] = {}
+                data['grpIeDetails'][currentGrpie]['ieTypeValue'] = mGroupedIeDefStart.group(2)
+                data['grpIeDetails'][currentGrpie]['instList'] = []
+                data['grpIeDetails'][currentGrpie]['instList'].append(currentInstance)
+                data['grpIeDetails'][currentGrpie][currentInstance] = {}
+                data['grpIeDetails'][currentGrpie][currentInstance]['instance'] = currentInstanceValue
+                grpIeData = data['grpIeDetails'][currentGrpie][currentInstance]
+                grpIeData['msgName'] = currentMsg
+                
+            elif mGroupedIeDefEnd:
+                state = 'EndDetected'
+                grpIeData = {} 
+                ieList = []
+                grpIeList=[]
+                ieDetailsList = []
+               
+                GenerateGrpIeClass.generateGroupedIeClasses(data)
+                GenerateGrpIeClass.prepareGrpIeMakeFile()
+                
+                
+            elif state == 'StartDetected':
+                state = 'IeListStart'
+                
+            elif state == 'IeListStart':
+                
+                if xlUtils.getCellValue(sheet,i,'D') != None:
+                    ieData = {}
+                    ieDescription = xlUtils.getCellValue(sheet,i,'D')
+                    ieData['ieDescription'] = xlUtils.getCellValue(sheet,i,'D')
+                    ieData['presence'] = xlUtils.getCellValue(sheet,i,'E')
+                    ieData['grouped'] = xlUtils.getCellValue(sheet,i,'B')
+                    ieData['cardinality'] = xlUtils.getCellValue(sheet,i,'C')
+                    ieData['instance'] = xlUtils.getCellValue(sheet,i,'H') 
+                    
+                    if ieData['cardinality'] == None:
+                        ieData['cardinality'] = 1 
+                    ieTypeDescription = xlUtils.getCellValue(sheet,i,'G')
+                    ieData['ieTypeDescription'] = ieTypeDescription
+                    
+                    ieVarName  = xlUtils.getVarNameFromString(ieDescription,0)
+                    
+                    ieTypeName  = xlUtils.getVarNameFromString(ieTypeDescription,1)
+                    
+                    if ieData['grouped'] == 'Yes':
+                        ieData['ieGroupTypeName'] = ieVarName.capitalize() + 'In' + currentMsg
+                        
+                    ieData['ieVarName'] = ieVarName
+                    ieData['ieTypeName'] = ieTypeName
+                    
+                    
+                    ieList.append(ieVarName)
+                    grpIeData['ieList'] = ieList
+                    grpIeData['ieDetails'] = {}
+                    grpIeData['ieDetails'][ieVarName] = ieData
+                    ieDetailsList.append(grpIeData['ieDetails'])
+                    grpIeData['ieDetails'] = ieDetailsList
+                    
+        
+    def generateGroupedIeClasses(data):
+        parsedData = data
+        
+        for grpIe in parsedData['grpIeList']:
+            
+            grpIeDetails = parsedData['grpIeDetails'][grpIe]
+            
+            GenerateGrpIeClass.generateGroupedIeClass(grpIeDetails,grpIe)
+            GenerateGrpIeClass.generateGroupedIeDataType(grpIeDetails, grpIe)
+    def generateGroupedIeClass(grpIeDetails,grpIe):
+        
+        templateData['fileName'] = grpIe[0].lower()+grpIe[1:] + 'Ie'
+        templateData['className'] = grpIe + 'Ie'
+        templateData['classNameUC'] = templateData['fileName'].upper()
+        fileName=templateData['fileName']
+
+        for inst in grpIeDetails['instList']:
+            instanceInfo = {}
+            instDetails  = grpIeDetails[inst]
+            GenerateGrpIeClass.generateGroupedIeInstanceClass(instDetails, inst)
+            
+            instanceInfo['className'] = inst
+            instanceInfo['fileName'] = inst[0].lower()+inst[1:]
+            instanceInfo['msgType'] =  instDetails['msgName'] + 'MsgType'
+            instanceInfo['instance'] = instDetails['instance']
+            
+            if instanceInfo not in templateData['instList']:
+                templateData['instList'].append(instanceInfo)
+            
+        templateData[fileName]=[inst for inst in templateData['instList'] if grpIe in inst['className']]                
+           
+        outputDir = '../../src/gtpV2Codec/ieClasses'
+        ttFileNameCpp = 'tts/grpietemplate.cpp.tt'
+        ttFileNameH = 'tts/grpietemplate.h.tt'
+        xlUtils.templateProcess(templateData,ttFileNameCpp,ttFileNameH,outputDir,outputDir)
+        
+        objectfile ='ieClasses/' + templateData['fileName'] + '.o'
+        sourcefile = 'ieClasses/' + templateData['fileName'] + '.cpp'
+        xlUtils.addToMakeSo('gtpV2Stack.so',objectfile,sourcefile)
+    
+    def generateGroupedIeDataType(grpIeDetails, grpIe):
+        grpIeInfo={}
+        
+        grpIeInfo['iePresenceList']=[]
+        grpIeTypeInfo={}
+        grpIeTypeInfo['grpIeTypeName']=grpIe + 'IeType'
+        grpIeTypeInfo['grpIeTypeValue']=grpIeDetails['ieTypeValue']
+        if grpIeTypeInfo not in grpIeDataTypeData['grpTypeList']:
+            grpIeDataTypeData['grpTypeList'].append(grpIeTypeInfo)
+        
+        for inst in grpIeDetails['instList']:
+            
+            instDetails  = grpIeDetails[inst]
+            grpIeInfo={}
+            grpIeInfo['iePresenceList']=[]
+            grpIeInfo['grpIeName']= inst+'Data'
+            grpIeInfo['ieList']=[]
+            for ieDict in instDetails['ieDetails']:
+                for ieDetails in ieDict:
+                    if ieDict[ieDetails]['presence']!='M':
+                        grpIeInfo['iePresenceList'].append(ieDict[ieDetails]['ieVarName']+'IePresent')
+                    ieInfo={}
+                    ieInfo['ieTypeName']=ieDict[ieDetails]['ieTypeName']+'IeData'
+                    ieInfo['ieVarName']=ieDict[ieDetails]['ieVarName']
+                    grpIeInfo['ieList'].append(ieInfo)
+        
+        if grpIeInfo not in grpIeDataTypeData['grpList']:
+            grpIeDataTypeData['grpList'].append(grpIeInfo)
+        template = Template()
+        ttFileNamefactoryH = 'tts/grpIeDataTypetemplate.h.tt'
+        outputDir = '../../src/gtpV2Codec/ieClasses/'
+        
+        if not os.path.exists(outputDir):
+            os.makedirs(outputDir)
+        outputFileName = 'gtpV2GrpIeDataTypes.h'
+        template.__init__({'OUTPUT' : outputFileName, 'OUTPUT_PATH' : outputDir})
+        template.process(ttFileNamefactoryH, {'tempdata' : grpIeDataTypeData})
+        
+    def generateGroupedIeInstanceClass(instDetails, inst):
+        templateInstData = {}
+        ieTypeList = []
+        ieTypeDetailsList = []
+       
+        ieInfoList =[]
+       
+        templateInstData['fileName'] = inst[0].lower()+inst[1:]
+        
+        templateInstData['msgClassName'] = inst
+        templateInstData['classNameUC'] = templateInstData['fileName'].upper()
+        
+        for ieEntry in instDetails['ieList']:
+            
+            ieInfo = {}
+            ieTypeInfo = {}
+            
+            ies = instDetails['ieDetails']
+            for x in ies:
+                
+                ie = x.get(ieEntry)
+                
+                if ie != None and ieEntry == ie.get('ieVarName'):
+                    ieInfo['ieName'] =  ie['ieVarName']
+                    ieInfo['ieVarName'] = ie['ieVarName']
+                    ieInfo['ieType'] = ie['ieTypeName']
+                    ieInfo['ieFileName'] = ie['ieTypeName'][0].lower()+ie['ieTypeName'][1:] + 'Ie'
+                    ieInfo['ieLocalVar'] = ie['ieTypeName'][0].lower()+ie['ieTypeName'][1:]
+                    ieInfo['iePresence'] = ie['presence']
+                    ieInfo['ieCardinality'] = ie['cardinality']
+                    ieInfo['instance'] = ie['instance']
+                    ieInfo['grouped'] = ie['grouped']
+                   
+                    ieType = ieInfo['ieType']
+                    
+                    ieTypeInfo['ieName'] =  ie['ieVarName']
+                    ieTypeInfo['ieVarName'] = ie['ieVarName']
+                    ieTypeInfo['ieType'] = ie['ieTypeName']
+                    ieTypeInfo['ieFileName'] = ie['ieTypeName'][0].lower()+ie['ieTypeName'][1:] + 'Ie'
+                    ieTypeInfo['ieLocalVar'] = ie['ieTypeName'][0].lower()+ie['ieTypeName'][1:]
+                    ieTypeInfo['iePresence'] = ie['presence']
+                    ieTypeInfo['ieCardinality'] = ie['cardinality']
+                    ieTypeInfo['instance'] = ie['instance']
+                    ieTypeInfo['grouped'] = ie['grouped']
+                                        
+                    if ieInfo['ieType'] not in ieTypeList:   
+                        ieTypeList.append(ieInfo['ieType'])
+                        templateInstData['ieTypeList'] = ieTypeList
+                                        
+                    if ieInfo not in ieInfoList:
+                                              
+                        ieInfoList.append(ieInfo)
+                        templateInstData['ieList'] = ieInfoList
+                    
+                    templateInstData['ieTypeDetails'] = {}
+                    templateInstData['ieTypeDetails'][ieType] = []
+                    if ieTypeInfo not in templateInstData['ieTypeDetails'][ieType]:
+                        templateInstData['ieTypeDetails'][ieType].append(ieTypeInfo)
+                        ieTypeDetailsList.append(templateInstData['ieTypeDetails'])
+                        templateInstData['ieTypeDetails'] = ieTypeDetailsList
+      
+        GenerateGrpIeClass.templateInstanceprocess(templateInstData)
+        outputDirCpp = 'ieClasses/'
+        objectfile = outputDirCpp +templateInstData['fileName'] + '.o'
+        sourcefile = outputDirCpp + templateInstData['fileName'] + '.cpp'
+        xlUtils.addToMakeSo('gtpV2Stack.so',objectfile,sourcefile)
+        
+    def templateInstanceprocess(templateInstData):
+        
+        ttFileNameInstCpp = 'tts/grpieinsttemplate.cpp.tt'
+        outputDir = '../../src/gtpV2Codec/ieClasses'
+        ttFileNameInstH = 'tts/grpieinsttemplate.h.tt'
+        xlUtils.templateProcess(templateInstData,ttFileNameInstCpp,ttFileNameInstH,outputDir,outputDir)
+            
+    def prepareGrpIeMakeFile():
+        outputDirCpp = 'ieClasses/manual/'
+        xlUtils.addToMakeSo("gtpV2Stack.so", outputDirCpp+'gtpV2GroupedIe.o',outputDirCpp+'gtpV2GroupedIe.cpp')
+                    
+GenerateGrpIeClass()
diff --git a/scripts/GtpV2StackCodeGen/iECodeGen.py b/scripts/GtpV2StackCodeGen/iECodeGen.py
new file mode 100644
index 0000000..2a90656
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/iECodeGen.py
@@ -0,0 +1,318 @@
+# Copyright 2019-present Infosys Limited     
+# SPDX-License-Identifier: Apache-2.0
+
+
+import re
+import os
+from template import Template
+from xlUtils import xlUtils,wb
+
+ieFactoryData = {}
+ieFactoryData['ieList'] = []
+
+ieDataTypeData = {}
+ieDataTypeData['ieTypeList'] = []
+ieDataTypeData['ieList'] = []
+class GenerateIeClass:
+    
+    def __init__( self ):
+        
+        self.ieParser()
+    
+    #Parse the data from excel sheet 'IE Modeling' 
+    #and build to a dict 'iedata'
+    def ieParser(self):
+        
+        sheet = wb['IE Modeling']
+        state = ''
+        
+        encodeSeq = []
+        byteLength = 0
+        currentType = ''
+        validation = ''
+        count = ''
+        decodeCondition = ''
+        encodeCondition = ''
+        typeVal = ''
+        presence = ''
+        bitLength = 0        
+        varDetailList = []
+        ieData = dict()         
+        ieTypeList = []
+        lengthStr = ''        
+        varType = ''
+        varName = ''
+        mType=0
+        varList=[]
+        grpIeList = []
+        
+        for i in range(1,sheet.max_row+1):
+            presence = ''
+            bitLength = 0
+            byteLength = 0
+            cell_value_B = xlUtils.getCellValue(sheet,i,'B')
+            cell_value_D = xlUtils.getCellValue(sheet,i,'D')
+            cell_value_H = xlUtils.getCellValue(sheet,i,'H')
+            
+            # Search pattern for IE definition start,end 
+            mGroupedIe = re.search('Grouped IE Definition:(\w+)',str(cell_value_B))
+            mIeDefStart = re.search('IE Definition Start:(\w+)',str(cell_value_B))
+            mIeDefEnd = re.search('IE Definition End:(\w+)' ,str(cell_value_B))
+             
+            if mGroupedIe:
+                
+                grpIeName = mGroupedIe.group(1)
+                grpIeList.append(grpIeName)
+                for grpie in grpIeList:
+                    self.generateIeFactory(grpie)
+                
+            if mIeDefStart:
+                currentType = mIeDefStart.group(1)
+                state = 'StartDetected'
+                ieTypeList.append(currentType)
+                
+            elif mIeDefEnd:
+                
+                state = 'EndDetected' 
+                self.templateIes(ieData,currentType)
+                self.generateIeFactory(currentType)
+                self.generateIeDataType(currentType,typeVal,varList)
+                self.prepareIeMakeFile()
+                varList = []
+                
+            elif state == 'StartDetected':
+                varDetailList = []
+                encodeSeq = []
+                
+                colDValue = str(cell_value_D)
+                mType = re.search('Type = (\d+)',colDValue)
+                mSpare = re.search('Spare',colDValue)
+                mInstance = re.search('Instance',str(cell_value_H))
+                
+                if mType:
+                    typeVal = mType.group(1)
+                    ieData['ieDetails'] = {}
+                    ieData['ieDetails'][currentType] = {}
+                    ieData['ieDetails'][currentType]['ieName'] = currentType
+                    ieData['ieDetails'][currentType]['ieTypeVal'] = typeVal
+                    
+                if mSpare and mInstance:
+                    state = 'TypeDefinitionStart'
+                                    
+            elif state == 'TypeDefinitionStart':
+                
+                (byteLength,lengthStr) = xlUtils.getByteLength(sheet,i)
+                
+                #for fields less than 1 bytelength
+                if byteLength == 0:
+                    
+                   for j in map(chr, range( ord('D'), ord('L'))):
+                       field = xlUtils.getCellValue(sheet,i,j)
+                       fieldDetails=dict()
+                       if field != None:
+                           
+                           bitLength = xlUtils.getBitLength(sheet,i,j) 
+                           (varName,varType,encodeCondition,decodeCondition,validation,count) = xlUtils.extractField(field)
+                           
+                           if varType == '':
+                               varType = 'Uint8'
+                           if bitLength == 8:
+                               byteLength = 1
+                               bitLength = 0        
+                           if varName != 'Spare':
+                               fieldDetails['varName']=varName
+                               fieldDetails['varType']=varType
+                               fieldDetails['presence']=presence
+                               varList.append(fieldDetails)
+                              
+                               ieData['varDetails'] = {}
+                               ieData['varDetails'][varName] = {}
+                               ieData['varDetails'][varName]['varType'] = varType
+                               ieData['varDetails'][varName]['decodeCondition'] = decodeCondition
+                               ieData['varDetails'][varName]['encodeCondition'] = encodeCondition
+                               ieData['varDetails'][varName]['validation'] = validation
+                               ieData['varDetails'][varName]['bitLength'] = bitLength
+                               ieData['varDetails'][varName]['byteLength'] = byteLength
+                               ieData['varDetails'][varName]['lengthStr'] = lengthStr
+                               ieData['varDetails'][varName]['presence'] = presence
+                               ieData['varDetails'][varName]['count'] = count
+                               varDetailList.append(ieData['varDetails'])
+                               ieData['varDetails'] = varDetailList
+                               
+                               encStrBit = 'encode:' + varName + ':' + str(bitLength) + ':Bits'
+                               encodeSeq.append(encStrBit)
+                               ieData['encodeSeq'] = encodeSeq
+                               
+                           else:
+                               skipStrBit = 'skip:'+ str(bitLength) + ':Bits'
+                               encodeSeq.append(skipStrBit)
+                               ieData['encodeSeq'] = encodeSeq
+                
+                #for fields of length 1 byte
+                else:
+                                        
+                    field = sheet.cell(row=i, column=4).value
+                    (varName,varType,encodeCondition,decodeCondition,validation,count) = xlUtils.extractField(field)
+                    fieldDetails=dict()
+                    if varType == '':
+                        varType = xlUtils.lengthToType(byteLength)
+                
+                    if varName != 'Spare':
+                        fieldDetails['varName']=varName
+                        fieldDetails['varType']=varType
+                        if xlUtils.getCellValue(sheet,i,'B') == 'Yes':
+                             presence = 'optional'
+                        fieldDetails['presence']=presence
+                        varList.append(fieldDetails)
+                                              
+                        ieData['varDetails'] = {}
+                        ieData['varDetails'][varName] = {}
+                        ieData['varDetails'][varName]['varType'] = varType
+                        ieData['varDetails'][varName]['decodeCondition'] = decodeCondition
+                        ieData['varDetails'][varName]['encodeCondition'] = encodeCondition
+                        ieData['varDetails'][varName]['validation'] = validation
+                        ieData['varDetails'][varName]['bitLength'] = bitLength
+                        ieData['varDetails'][varName]['byteLength'] = byteLength
+                        ieData['varDetails'][varName]['lengthStr'] = lengthStr
+                        ieData['varDetails'][varName]['count'] = count
+                                           
+                        if xlUtils.getCellValue(sheet,i,'B') == 'Yes':
+                             presence = 'optional' 
+                             
+                             ieData['varDetails'][varName]['presence'] = presence
+                        varDetailList.append(ieData['varDetails'])
+                        ieData['varDetails'] = varDetailList
+                        
+                        encstrbyte = 'encode:' + varName + ':' + str(byteLength) + ':Bytes'
+                        encodeSeq.append(encstrbyte)
+                        ieData['encodeSeq'] = encodeSeq
+                    else:
+                        skipstrbyte = 'skip:'+ str(byteLength) + ':Bytes'
+                        encodeSeq.append(skipstrbyte)
+                        ieData['encodeSeq'] = encodeSeq    
+        return ieData    
+    
+    def templateIes(self,ieData,currentType):
+        
+        templateData = dict()  
+        varDetailsList = []
+        sequenceList = []
+        varDetailsList = ieData['varDetails']
+        templateData['className'] = ieData['ieDetails'][currentType]['ieName']+'Ie'
+        templateData['fileName'] = templateData['className'][0].lower() + templateData['className'][1:] 
+        templateData['classNameUC'] = templateData['className'].upper()
+        templateData['ieTypeVal'] = ieData['ieDetails'][currentType]['ieTypeVal']
+        
+        #building the dictionary obtained to a dict 'templateData'
+        #which is the input to template process 
+        
+        for en in ieData['encodeSeq']:   
+            mEncode = re.search('encode:(\w+):',en)
+            mSkip = re.search('skip:(\d+):(\w+)',en)
+            item = dict()
+            if mSkip:
+                bitByte = mSkip.group(2)
+                skipValue = mSkip.group(1)
+                item['skipType'] = 'y'
+                item['bitByte'] = bitByte
+                item['skipValue'] = skipValue
+            elif mEncode:
+                varName = mEncode.group(1)
+                for variableDetails in varDetailsList:
+                    for key,value in variableDetails.items():
+                        if key == varName:
+                            item['fieldName'] = varName
+                            if value['bitLength'] != 0:
+                                item['bitField'] = 'y'
+                                item['fieldSize'] = value['bitLength']
+                                item['leafType'] = 'y'
+                            else:
+                                item['fieldSize'] = value['byteLength']
+                            if value['decodeCondition'] != '':
+                                item['decodeConditional'] = 'y'
+                                item['decodeCondition'] = value['decodeCondition']
+                            if value['encodeCondition'] != '':
+                                item['encodeConditional'] = 'y'
+                                item['encodeCondition'] = value['encodeCondition']
+                            if value.get('presence') == 'optional':
+                                item['presence'] = 'optional'
+                            item['fieldType'] = value['varType']
+                            mUint = re.search('^Uint(\d+)$',value['varType'])
+                            if mUint or value['varType'] == 'bool':
+                                item['leafType'] = 'y'                    
+                            else:
+                                if value['lengthStr'] == 'EOI' or value['lengthStr'] == '':
+                                    item['length'] = 'lengthLeft'
+                                else:
+                                    item['length'] = value['lengthStr']
+                            if value['validation'] != '':
+                    
+                                item['validationPresent'] = 'y'
+                                item['validationRule'] = value['validation']
+                            mArray = re.search('Array',value['varType'])
+                            if mArray:
+                                item['arrayType']='y'
+                                if value['count'] =='':
+                                    item['count']=0
+                                else:
+                                    item['count']=value['count']
+                                
+            if  item != {}:
+                sequenceList.append(item)
+                templateData['sequence'] = sequenceList
+   
+        outputDir = '../../src/gtpV2Codec/ieClasses'
+        ttFileNameCpp = 'tts/ietemplate.cpp.tt'
+        ttFileNameH = 'tts/ietemplate.h.tt'
+        xlUtils.templateProcess(templateData,ttFileNameCpp,ttFileNameH,outputDir,outputDir)
+        
+        objectFile = 'ieClasses/' +templateData['fileName'] + '.o'
+        sourceFile ='ieClasses/' + templateData['fileName'] + '.cpp'
+        xlUtils.addToMakeSo('gtpV2Stack.so',objectFile,sourceFile)
+       
+    def ieFactoryTemplate(self,ieFactoryData):
+        
+        ieFactoryData['fileName']='gtpV2IeFactory'
+        ttFileNameFactoryCpp = 'tts/iefactorytemplate.cpp.tt'
+        outputDir = '../../src/gtpV2Codec/ieClasses'
+        ttFileNamefactoryH = 'tts/iefactorytemplate.h.tt'
+        xlUtils.templateProcess(ieFactoryData,ttFileNameFactoryCpp,ttFileNamefactoryH,outputDir,outputDir)
+        
+    def generateIeFactory(self,currentType):
+        ieinfo = {}
+        ieinfo['className'] = currentType + 'Ie'
+        ieinfo['ieFileName'] = currentType[0].lower()+currentType[1:] + 'Ie'
+        if ieinfo not in ieFactoryData['ieList']:
+            ieFactoryData['ieList'].append(ieinfo)
+        outputDir = 'ieClasses/'
+        self.ieFactoryTemplate(ieFactoryData)
+        xlUtils.addToMakeSo('gtpV2Stack.so',outputDir+'gtpV2IeFactory.o',outputDir+'gtpV2IeFactory.cpp')
+        
+    def generateIeDataType(self,currentType,typeVal,varList):
+        ieinfo = {}
+        ieTypeInfo={}    
+        ieinfo['ieName'] = currentType + 'IeData'
+        ieinfo['varList'] = varList
+        ieTypeInfo['ieName']=currentType + 'IeType'
+        ieTypeInfo['value']=typeVal
+        if ieinfo not in ieDataTypeData['ieList']:
+            ieDataTypeData['ieList'].append(ieinfo)
+        if ieTypeInfo not in ieDataTypeData['ieTypeList']:
+            ieDataTypeData['ieTypeList'].append(ieTypeInfo)
+        #print(ieDataTypeData)
+        template = Template()
+        ttFileNamefactoryH = 'tts/ieDataTypetemplate.h.tt'
+        outputDir = '../../src/gtpV2Codec/ieClasses'
+        
+        if not os.path.exists(outputDir):
+            os.makedirs(outputDir)
+        outputFileName = 'gtpV2IeDataTypes.h'
+        template.__init__({'OUTPUT' : outputFileName, 'OUTPUT_PATH' : outputDir})
+        template.process(ttFileNamefactoryH, {'tempdata' : ieDataTypeData})
+        
+    def prepareIeMakeFile(self):
+        outputDir = 'ieClasses/'
+        xlUtils.addToMakeSo('gtpV2Stack.so', outputDir+'dataTypeCodecUtils.o', outputDir+'dataTypeCodecUtils.cpp')
+        xlUtils.addToMakeSo('gtpV2Stack.so', outputDir+'manual/gtpV2Ie.o', outputDir+'manual/gtpV2Ie.cpp')
+        
+GenerateIeClass()
diff --git a/scripts/GtpV2StackCodeGen/msgCodeGen.py b/scripts/GtpV2StackCodeGen/msgCodeGen.py
new file mode 100644
index 0000000..cfa7281
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/msgCodeGen.py
@@ -0,0 +1,267 @@
+# Copyright 2019-present Infosys Limited     
+# SPDX-License-Identifier: Apache-2.0
+
+
+import re
+
+import os
+from template import Template
+
+
+from xlUtils import xlUtils,wb
+msgFactoryData = {}
+msgFactoryData['msgList'] = []
+msgDataTypeData = {}
+msgDataTypeData['msgTypeList'] = []
+msgDataTypeData['msgList'] = []
+class GenerateMsgClass():
+    def __init__( self ):
+        self.msgParser()
+    
+    def msgParser(self):
+        
+        sheet = wb['Message Modeling']
+        state = ''
+        ieDetailList = []
+        ieList = []
+        
+        currentMessage = ''
+        msgValue = 0
+        msgData = {}
+        
+        
+        for i in range(1,sheet.max_row+1):
+            
+            cell_value_B = xlUtils.getCellValue(sheet,i,'B')
+            
+            mMsgDefinitionStart = re.search('Message Definition Start:(\w+):(\d+)',str(cell_value_B))
+            mMsgDefinitionEnd = re.search('Message Definition End:(\w+)',str(cell_value_B))
+            mResponseMsg = re.search('ResponseMessage',str(cell_value_B))
+            mGrouped = re.search('Grouped',str(cell_value_B))
+            
+            
+            if mMsgDefinitionStart:
+                
+                
+                state = 'StartDetected'
+                currentMessage = mMsgDefinitionStart.group(1)
+                msgValue = mMsgDefinitionStart.group(2)
+               
+                
+            if mMsgDefinitionEnd:
+                
+                ieList = []
+                ieDetailList = []
+                state = 'EndDetected'
+                
+                GenerateMsgClass.templateIes(msgData,currentMessage)
+                GenerateMsgClass.generateMsgFactory(msgData,currentMessage)
+                GenerateMsgClass.generateMsgDataType(msgData,currentMessage)
+                GenerateMsgClass.prepareMsgMakeFile()
+                
+            elif state == 'StartDetected':
+                
+                msgData['msgDetails'] = {}
+                msgData['msgDetails'][currentMessage] = {}
+                msgData['msgDetails'][currentMessage]['msgValue'] = msgValue
+                msgData['msgDetails'][currentMessage]['msgDataType'] = currentMessage + 'MsgData'
+                msgData['msgDetails'][currentMessage]['msgCategory'] = "RequestMessage"
+                if mResponseMsg:
+                    
+                    msgData['msgDetails'][currentMessage]['msgCategory'] = "ResponseMessage"
+                elif mGrouped:
+                    state = 'IeListStart'
+                
+                
+                    
+            elif state == 'IeListStart':
+                
+                if xlUtils.getCellValue(sheet,i,'D') != None:
+                    
+                    ieDescription  = xlUtils.getCellValue(sheet,i,'D')
+                    presence = xlUtils.getCellValue(sheet,i,'E')
+                    grouped = xlUtils.getCellValue(sheet,i,'B')
+                    cardinality = xlUtils.getCellValue(sheet,i,'C')
+                    instance = xlUtils.getCellValue(sheet,i,'H')
+                    msgData['ieDetails'] = {}
+                    msgData['ieDetails'][ieDescription] = {}
+                    msgData['ieDetails'][ieDescription]['ieDescription'] = ieDescription
+                    msgData['ieDetails'][ieDescription]['presence'] = presence
+                    msgData['ieDetails'][ieDescription]['grouped'] = grouped
+                    msgData['ieDetails'][ieDescription]['cardinality'] = cardinality
+                    msgData['ieDetails'][ieDescription]['instance'] = instance
+                    
+                    if msgData['ieDetails'][ieDescription]['cardinality'] is None:
+                        msgData['ieDetails'][ieDescription]['cardinality'] = 1
+                    ieTypeDescription = xlUtils.getCellValue(sheet,i,'G')
+                    msgData['ieDetails'][ieDescription]['ieTypeDescription'] = ieTypeDescription
+                    
+                    ieVarName = xlUtils.getVarNameFromString(ieDescription,0)
+                    ieTypeName  = xlUtils.getVarNameFromString(ieTypeDescription,1)
+                    ieVarName = ieVarName.replace('/','')
+                    
+                    msgData['ieDetails'][ieDescription]['ieGroupTypeName'] = ''
+                    if msgData['ieDetails'][ieDescription]['grouped'] == 'Yes':
+                        msgData['ieDetails'][ieDescription]['ieGroupTypeName'] = ieVarName + 'In' + currentMessage
+                    msgData['ieDetails'][ieDescription]['ieVarName'] = ieVarName
+                    msgData['ieDetails'][ieDescription]['ieTypeName'] = ieTypeName      
+                               
+                    if ieVarName!="privateExtension":
+                        ieDetailList.append(msgData['ieDetails'])
+                        
+                        ieList.append(ieVarName)
+                    msgData['ieList'] = ieList
+                    msgData['ieDetails'] = ieDetailList
+                      
+        return msgData
+    
+    
+    def templateIes(msgData,currentMessage):
+        templateData = dict()
+        ieListTemplate = []
+        ieTypeTemplate = []
+        ieTypeDetailList = []
+        ieTypeList = []
+        templateData['fileName'] = currentMessage[0].lower()+currentMessage[1:] + 'Msg'
+        templateData['msgClassName'] = currentMessage[0].upper()+currentMessage[1:] + 'Msg'
+        templateData['classNameUC'] = templateData['fileName'].upper()
+        templateData['msgCategory'] = msgData['msgDetails'][currentMessage]['msgCategory']
+        
+        for ieDetail in msgData['ieDetails']:
+            for key,value in ieDetail.items():
+                for ie in msgData['ieList']:
+                    ieInfo = {}
+                    ieTypeInfo = {}
+                    if value['ieVarName'] == ie:
+
+                        ieInfo['ieName'] = value['ieVarName']
+                        ieInfo['ieVarName'] = value['ieVarName']
+                        ieInfo['ieType'] = value['ieTypeName']
+                        ieInfo['ieFileName'] = value['ieTypeName'][0].lower()+value['ieTypeName'][1:] + 'Ie'
+                        ieInfo['ieLocalVar'] = value['ieTypeName'][0].lower()+value['ieTypeName'][1:]
+                        ieInfo['iePresence'] = value['presence']
+                        ieInfo['ieCardinality'] = value['cardinality']
+                        ieInfo['instance'] = value['instance']
+                        ieInfo['grouped'] = value['grouped']
+                        ieInfo['grpIeInstClassName'] = value['ieGroupTypeName']
+                        if ieInfo['grouped']=='Yes':
+                            ieInfo['grpIeInstClassName'] = value['ieGroupTypeName'][0].upper()+value['ieGroupTypeName'][1:]
+                        ieInfo['grpIeInstFileName'] = value['ieGroupTypeName']
+                        
+                        ieType = ieInfo['ieType']
+                        ieTypeInfo['ieName'] = value['ieVarName']
+                        ieTypeInfo['ieVarName'] = value['ieVarName']
+                        ieTypeInfo['ieType'] = value['ieTypeName']
+                        ieTypeInfo['ieFileName'] = value['ieTypeName'][0].lower()+value['ieTypeName'][1:] + 'Ie'
+                        ieTypeInfo['ieLocalVar'] = value['ieTypeName'].capitalize()
+                        ieTypeInfo['iePresence'] = value['presence']
+                        ieTypeInfo['ieCardinality'] = value['cardinality']
+                        ieTypeInfo['instance'] = value['instance']
+                        ieTypeInfo['grouped'] = value['grouped']
+                        ieTypeInfo['grpIeInstClassName'] = value['ieGroupTypeName']
+                        if ieTypeInfo['grouped']=='Yes':
+                            ieTypeInfo['grpIeInstClassName'] = value['ieGroupTypeName'][0].upper()+value['ieGroupTypeName'][1:]
+                        ieTypeInfo['grpIeInstFileName'] = value['ieGroupTypeName'].capitalize()
+                        
+                       
+                        ieListTemplate.append(ieInfo)
+                        templateData['ieList'] = ieListTemplate
+                       
+                        if ieInfo['ieType'] not in ieTypeList:   
+                            ieTypeList.append(ieInfo['ieType'])
+                            templateData['ieTypeList'] = ieTypeList
+                            
+                        ieTypeTemplate = []
+                        ieTypeTemplate.append(ieTypeInfo)
+                        templateData['ieTypeDetails'] = {}   
+                        templateData['ieTypeDetails'][ieType] = ieTypeTemplate
+                        
+                        ieTypeDetailList.append(templateData['ieTypeDetails'])
+                        templateData['ieTypeDetails'] = ieTypeDetailList
+        
+        outputDir = '../../src/gtpV2Codec/msgClasses'
+        ttFileNameCpp = 'tts/msgtemplate.cpp.tt'
+        ttFileNameH = 'tts/msgtemplate.h.tt'
+        xlUtils.templateProcess(templateData,ttFileNameCpp,ttFileNameH,outputDir,outputDir)
+        
+        objectFile = 'msgClasses/' +templateData['fileName'] + '.o'
+        sourceFile = 'msgClasses/' + templateData['fileName'] + '.cpp'
+        xlUtils.addToMakeSo('gtpV2Stack.so',objectFile,sourceFile)
+       
+    def generateMsgFactory(msgData,currentMessage):
+        msgInfo = {}
+        
+        msgInfo['className'] = currentMessage + 'Msg'
+        msgInfo['msgFileName'] = currentMessage[0].lower()+currentMessage[1:] + 'Msg'
+        msgInfo['dataMember'] = currentMessage[0].lower()+currentMessage[1:] + 'StackData'
+        if msgInfo not in msgFactoryData['msgList']:
+            msgFactoryData['msgList'].append(msgInfo)
+        outputDirCpp = 'msgClasses/'
+        GenerateMsgClass.msgfactoryStacktemplate(msgFactoryData)
+        xlUtils.addToMakeSo('gtpV2Stack.so',outputDirCpp+'gtpV2MsgFactory.o',outputDirCpp+'gtpV2MsgFactory.cpp')
+        xlUtils.addToMakeSo('gtpV2Stack.so','gtpV2Stack.o','gtpV2Stack.cpp')
+        
+    def msgfactoryStacktemplate(msgFactoryData):
+ 
+        ttFileNamefactoryCpp = 'tts/msgfactorytemplate.cpp.tt'
+        outputDir = '../../src/gtpV2Codec/msgClasses'   
+        msgFactoryData['fileName'] = 'gtpV2MsgFactory'
+        ttFileNamefactoryH = 'tts/msgfactorytemplate.h.tt'
+        xlUtils.templateProcess(msgFactoryData,ttFileNamefactoryCpp,ttFileNamefactoryH,outputDir,outputDir)
+        
+        ttFileNameStackCpp = 'tts/stacktemplate.cpp.tt'
+        outputDir = '../../src/gtpV2Codec/'
+        msgFactoryData['fileName'] = 'gtpV2Stack' 
+        ttFileNameStackH = 'tts/stacktemplate.h.tt'
+
+        xlUtils.templateProcess(msgFactoryData,ttFileNameStackCpp,ttFileNameStackH,outputDir,outputDir)
+        
+        
+      
+    def prepareMsgMakeFile():
+        outputDir = 'msgClasses/manual/'
+        xlUtils.addToMakeSo('gtpV2Stack.so', outputDir+'gtpV2Message.o', outputDir+'gtpV2Message.cpp')
+    def generateMsgDataType(msgData,currentMessage):
+        msginfo = {}
+        msgTypeInfo={}    
+        msginfo['msgDataName'] = currentMessage + 'MsgData'
+        msginfo['ieDetails']=[]
+        msgTypeInfo['msgDataType']=currentMessage + 'MsgType'
+        msgTypeInfo['msgValue']=msgData['msgDetails'][currentMessage]['msgValue']
+        
+        if  msgTypeInfo not in msgDataTypeData['msgTypeList']:
+            msgDataTypeData['msgTypeList'].append(msgTypeInfo)
+        
+        for ieDetail in msgData['ieDetails']:
+            for key,value in ieDetail.items():
+                for ie in msgData['ieList']:
+                    ieInfo = {}
+                    
+                    if value['ieVarName'] == ie:
+                        ieInfo['ieName'] = value['ieVarName']
+                        ieInfo['ieVarName'] = value['ieVarName']
+                        ieInfo['ieType'] = value['ieTypeName']
+                        ieInfo['iePresence'] = value['presence']
+                        ieInfo['ieCardinality'] = value['cardinality']
+                        ieInfo['grouped'] = value['grouped']
+                        ieInfo['grpIeInstClassName'] = value['ieGroupTypeName']
+                        if ieInfo['grouped']=='Yes':
+                            ieInfo['grpIeInstClassName'] = value['ieGroupTypeName'][0].upper()+value['ieGroupTypeName'][1:]
+                        ieInfo['grpIeInstFileName'] = value['ieGroupTypeName']
+                        if ieInfo not in msginfo['ieDetails']:
+                            msginfo['ieDetails'].append(ieInfo)
+        if msginfo not in msgDataTypeData['msgList']:
+            msgDataTypeData['msgList'].append(msginfo)
+                        
+        template = Template()
+        ttFileNamefactoryH = 'tts/msgDataTypetemplate.h.tt'
+        outputDir = '../../src/gtpV2Codec/msgClasses'
+        
+        if not os.path.exists(outputDir):
+            os.makedirs(outputDir)
+        outputFileName = 'gtpV2MsgDataTypes.h'
+        template.__init__({'OUTPUT' : outputFileName, 'OUTPUT_PATH' : outputDir})
+        template.process(ttFileNamefactoryH, {'tempdata' : msgDataTypeData})
+    
+        
+GenerateMsgClass()
\ No newline at end of file
diff --git a/scripts/GtpV2StackCodeGen/startCodeGen.py b/scripts/GtpV2StackCodeGen/startCodeGen.py
new file mode 100644
index 0000000..a3a2a27
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/startCodeGen.py
@@ -0,0 +1,16 @@
+
+# Copyright 2019-present Infosys Limited     
+# SPDX-License-Identifier: Apache-2.0   
+
+from iECodeGen import GenerateIeClass
+from datatypeCodeGen import GenerateDataTypeClass
+from xlUtils import xlUtils
+from msgCodeGen import GenerateMsgClass
+from groupedIECodeGen import GenerateGrpIeClass
+
+GenerateIeClass()
+GenerateDataTypeClass()
+GenerateMsgClass()
+GenerateGrpIeClass()
+
+xlUtils.generateMakeFile()
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
diff --git a/scripts/GtpV2StackCodeGen/xlUtils.py b/scripts/GtpV2StackCodeGen/xlUtils.py
new file mode 100644
index 0000000..1af0983
--- /dev/null
+++ b/scripts/GtpV2StackCodeGen/xlUtils.py
@@ -0,0 +1,219 @@
+# Copyright 2019-present Infosys Limited    
+# SPDX-License-Identifier: Apache-2.0   
+
+import re
+from template import Template
+import os
+from openpyxl import load_workbook
+
+libData = {}
+progData = {}
+template = Template()
+wb = load_workbook('dataModel/prototypeV8.xlsx')
+class xlUtils:
+    def __init__(self):
+        pass
+    
+   
+    def extractField(field):
+        varName = ''
+        varType = ''
+        encodeCondition = ''
+        decodeCondition = ''
+        validation = ''
+        count = ''
+        mVarName = re.search('^(\w+)',str(field))
+        mVarType = re.search(':Type\[(\w+)\]',str(field))
+        mEnCond = re.search(':Condition\[([^\:]*)\]',str(field))
+        mDeCond = re.search(':DecodeCondition\[([^\:]*)]',str(field))
+        mValid = re.search(':Validation\[([^\:]+)\]',str(field))
+        mCount = re.search(':Count\[([^\:]*)]',str(field))
+        if mVarName:
+            varName = mVarName.group(1)
+          
+        if mVarType:
+            varType = mVarType.group(1)
+           
+        if mEnCond:
+            encodeCondition = mEnCond.group(1)
+            
+        if mDeCond:
+            decodeCondition = mDeCond.group(1)
+        else:
+            if mEnCond:
+                decodeCondition = mEnCond.group(1)
+            
+            
+        if mValid:
+            validation = mValid.group(1)
+            dataVarName = 'data.' + varName
+            validation = re.sub(r'\$.',dataVarName,validation)
+
+        if mCount:
+            count =  mCount.group(1)
+            
+        return (varName,varType,encodeCondition,decodeCondition,validation,count)
+    
+    def lengthToType(byteLength):
+        lTdict = {1:'Uint8',2:'Uint16',3:'Uint32',4:'Uint32',5:'Uint64',6:'Uint64',7:'Uint64',8:'Uint64',65535:'Uint8',9:'Uint8',12:'Uint8'}
+        return lTdict[byteLength]
+     
+    def getByteLength(sheet,i): 
+        length = 0
+        lengthStr = ''
+        cell_value_C = xlUtils.getCellValue(sheet,i,'C')
+        octets =  str(cell_value_C) 
+        
+        mTo = re.search('to',str(octets)) 
+        mVar = re.search('^variable\[(.*)]',str(octets))
+        mToD = re.search('^(\d+) to (\d+)',str(octets))
+        mToWD = re.search('^(\w) to (\w)\+(\d+)',str(octets))
+        mToWWD = re.search('^(\w)\+(\d+) to (\w)\+(\d+)',str(octets))
+        
+        if not mTo:
+            if mVar:
+                lenStr = mVar.group(1)
+                length = 65535
+                lengthStr = lenStr
+                                           
+            elif xlUtils.getBitLength(sheet,i,'D') == 8:
+                length = 1
+                
+        else:
+            if mToD:
+                toD = mToD.group(1)
+                toD2 = mToD.group(2)
+                length = int(toD2) - int(toD) + 1
+                
+            elif mToWD:
+                ToWD = mToWD.group(3)
+                length = int(ToWD) + 1
+                            
+            elif mToWWD:
+                ToWWD2 = mToWWD.group(2)
+                ToWWD4 = mToWWD.group(4)
+                length = int(ToWWD4) - int(ToWWD2) + 1        
+        return (length,lengthStr)
+    
+    def getBitLength(sheet,i,j):
+        length = 0
+        fieldName = xlUtils.getCellValue(sheet,i,j)
+        mcolDtoK = re.search('[D-K]',j)
+        if fieldName != None and mcolDtoK:
+           for k in map(chr, range( ord(j), ord('L'))):
+               fName = xlUtils.getCellValue(sheet,i,k)
+              
+               if length == 0:
+                   length = length + 1
+                   
+               elif fName == None:
+                   length = length + 1
+            
+               else:
+                   break
+        return length
+    
+    
+    def getCellValue(sheet,row,column):
+        colNum = 0
+        chartoint = {'A' : 1,'B' : 2, 'C' : 3, 'D' : 4, 'E' : 5, 'F' : 6, 'G' : 7,
+               'H' : 8, 'I' : 9, 'J' : 10, 'K' : 11, 'L' : 12, 'M' : 13, 'N' : 14,
+               'O' : 15, 'P' : 16, 'Q' : 17, 'R' : 18, 'S' : 19, 'T' : 20, 'U' : 21,
+               'V' : 22, 'W' : 23, 'X' : 24, 'Y' : 25, 'Z' : 26}
+        
+        colNum = chartoint[column]
+        cellvalue = sheet.cell(row=row, column=colNum).value
+        return cellvalue
+    
+    def getVarNameFromString(localString,typeName):
+          
+        localString = localString.lower()
+        varName = ''
+        localString = re.sub(r'\(.*\)'," ",localString)
+        localString=localString.replace('/'," ")
+        localString = re.sub('-'," ",localString)
+        tokens = [x.capitalize() for x in localString.split(" ")]
+        varName = varName.join(tokens)
+        varName = varName[0].upper() + varName[1:]
+        if typeName == 1:
+            return varName
+        else:
+            return varName[0].lower() + varName[1:]
+        
+    def templateProcess(templateData,ttFileNameCpp,ttFileNameH,outputDirCpp,outputDirH):
+        
+        
+        template = Template()
+        
+        if not os.path.exists(outputDirCpp):
+            os.makedirs(outputDirCpp)
+        outputFileNameCpp = templateData['fileName'] + '.cpp'
+        
+        template.__init__({'OUTPUT' : outputFileNameCpp, 'OUTPUT_PATH' : outputDirCpp})
+        template.process(ttFileNameCpp, {'tempdata' : templateData})
+        
+
+        if not os.path.exists(outputDirH):
+            os.makedirs(outputDirH)
+        outputFileNameH = templateData['fileName'] + '.h'
+        template.__init__({'OUTPUT' : outputFileNameH, 'OUTPUT_PATH' : outputDirH})
+        template.process(ttFileNameH, {'tempdata' : templateData})
+        
+    def addToMakeSo(libName,objFile,srcFile):
+       
+        fileData = {}
+        fileData['objFile'] = objFile
+        fileData['sourceFile'] = srcFile
+        if libName not in libData:
+            lib = libName
+            lib = re.sub(r'.so','',lib)
+            libData[libName] = {}
+            libData[libName]['libName'] = lib
+            libData[libName]['fileList'] = []
+        if fileData not in libData[libName]['fileList']:
+            libData[libName]['fileList'].append(fileData)
+       
+    def addToMakeExe(progName,objFile,srcFile):
+        fileData = {}
+        fileData['objFile'] = objFile
+        fileData['sourceFile'] = srcFile
+        
+        if progName not in progData:
+            prog = progName
+            prog = re.sub(r'.exe','',prog)
+            progData[progName] = {}
+            progData[progName]['progName'] = prog
+            
+        progData[progName]['fileList'] = []
+        progData[progName]['fileList'].append(fileData)
+        
+    def addSoToMakeExe(progName,soName):
+        if progName not in progData:
+            prog = progName
+            prog = re.sub(r'.exe','',prog)
+            progData[progName] = {}
+            progData[progName]['progName'] = prog
+            
+            progData[progName]['soList'] = []
+        progData[progName]['soList'].append(soName)
+       
+    def generateMakeFile():
+        makeFileData = {}
+       
+        for libr in libData.keys():
+             makeFileData['libList'] = []
+             makeFileData['libList'].append(libData[libr])
+        for prog in progData.keys():
+            makeFileData['progList']=[]
+            makeFileData['progList'].append(progData[prog])
+        
+        
+        ttFileName = 'tts/makefiletemplate.tt'
+       
+        fileName = 'Makefile'
+        outputDir='../../src/gtpV2Codec'
+        
+        template.__init__({'OUTPUT' : fileName, 'OUTPUT_PATH' : outputDir})
+        template.process(ttFileName, {'makefiledata': makeFileData})
+        
+xlUtils()