[VOL-3538] Store unsupported OMCI-MEs into DB

Change-Id: I8879313c1321fff9298854a4296a57eeb7b84919
diff --git a/internal/pkg/devdb/onu_device_db.go b/internal/pkg/devdb/onu_device_db.go
index 008c37c..d3338c8 100755
--- a/internal/pkg/devdb/onu_device_db.go
+++ b/internal/pkg/devdb/onu_device_db.go
@@ -19,9 +19,11 @@
 
 import (
 	"context"
+	"encoding/hex"
 	"fmt"
 	"reflect"
 	"sort"
+	"strconv"
 	"sync"
 
 	me "github.com/opencord/omci-lib-go/v2/generated"
@@ -30,12 +32,28 @@
 
 type meDbMap map[me.ClassID]map[uint16]me.AttributeValueMap
 
-//OnuDeviceDB structure holds information about known ME's
+// UnknownMeName type to be used for unknown ME names
+type UnknownMeName string
+
+// allowed values for type UnknownMeName
+const (
+	CUnknownItuG988ManagedEntity        = "UnknownItuG988ManagedEntity"
+	CUnknownVendorSpecificManagedEntity = "UnknownVendorSpecificManagedEntity"
+)
+
+type unknownMeAttribs struct {
+	AttribMask  string `json:"AttributeMask"`
+	AttribBytes string `json:"AttributeBytes"`
+}
+type unknownMeDbMap map[UnknownMeName]map[me.ClassID]map[uint16]unknownMeAttribs
+
+//OnuDeviceDB structure holds information about ME's
 type OnuDeviceDB struct {
-	ctx      context.Context
-	deviceID string
-	MeDb     meDbMap
-	meDbLock sync.RWMutex
+	ctx         context.Context
+	deviceID    string
+	MeDb        meDbMap
+	meDbLock    sync.RWMutex
+	UnknownMeDb unknownMeDbMap
 }
 
 //NewOnuDeviceDB returns a new instance for a specific ONU_Device_Entry
@@ -45,6 +63,7 @@
 	OnuDeviceDB.ctx = ctx
 	OnuDeviceDB.deviceID = aDeviceID
 	OnuDeviceDB.MeDb = make(meDbMap)
+	OnuDeviceDB.UnknownMeDb = make(unknownMeDbMap)
 
 	return &OnuDeviceDB
 }
@@ -57,32 +76,22 @@
 	if me.OnuDataClassID == meClassID {
 		return
 	}
-
-	//logger.Debugw(ctx,"Search for key data :", log.Fields{"deviceId": OnuDeviceDB.deviceID, "meClassID": meClassID, "meEntityID": meEntityID})
-	meInstMap, ok := OnuDeviceDB.MeDb[meClassID]
+	_, ok := OnuDeviceDB.MeDb[meClassID]
 	if !ok {
 		logger.Debugw(ctx, "meClassID not found - add to db :", log.Fields{"device-id": OnuDeviceDB.deviceID})
-		meInstMap = make(map[uint16]me.AttributeValueMap)
-		OnuDeviceDB.MeDb[meClassID] = meInstMap
+		OnuDeviceDB.MeDb[meClassID] = make(map[uint16]me.AttributeValueMap)
+		OnuDeviceDB.MeDb[meClassID][meEntityID] = make(me.AttributeValueMap)
 		OnuDeviceDB.MeDb[meClassID][meEntityID] = meAttributes
 	} else {
-		meAttribs, ok := meInstMap[meEntityID]
+		meAttribs, ok := OnuDeviceDB.MeDb[meClassID][meEntityID]
 		if !ok {
-			/* verbose logging, avoid in >= debug level
-			logger.Debugw(ctx,"meEntityId not found - add to db :", log.Fields{"device-id": OnuDeviceDB.deviceID})
-			*/
-			meInstMap[meEntityID] = meAttributes
+			OnuDeviceDB.MeDb[meClassID][meEntityID] = make(me.AttributeValueMap)
+			OnuDeviceDB.MeDb[meClassID][meEntityID] = meAttributes
 		} else {
-			/* verbose logging, avoid in >= debug level
-			logger.Debugw(ctx,"ME-Instance exists already: merge attribute data :", log.Fields{"device-id": OnuDeviceDB.deviceID, "meAttribs": meAttribs})
-			*/
 			for k, v := range meAttributes {
 				meAttribs[k] = v
 			}
-			meInstMap[meEntityID] = meAttribs
-			/* verbose logging, avoid in >= debug level
-			logger.Debugw(ctx,"ME-Instance updated :", log.Fields{"device-id": OnuDeviceDB.deviceID, "meAttribs": meAttribs})
-			*/
+			OnuDeviceDB.MeDb[meClassID][meEntityID] = meAttribs
 		}
 	}
 }
@@ -151,7 +160,34 @@
 	logger.Debugw(ctx, "ME instances stored for :", log.Fields{"device-id": OnuDeviceDB.deviceID})
 	for meClassID, meInstMap := range OnuDeviceDB.MeDb {
 		for meEntityID, meAttribs := range meInstMap {
-			logger.Debugw(ctx, "ME instance: ", log.Fields{"meClassID": meClassID, "meEntityID": meEntityID, "meAttribs": meAttribs, "device-id": OnuDeviceDB.deviceID})
+			logger.Debugw(ctx, "ME instance: ", log.Fields{"meClassID": meClassID, "meEntityID": meEntityID, "meAttribs": meAttribs,
+				"device-id": OnuDeviceDB.deviceID})
+		}
+	}
+}
+
+//PutUnknownMe puts an unknown ME instance into internal ONU DB
+func (OnuDeviceDB *OnuDeviceDB) PutUnknownMe(ctx context.Context, aMeName UnknownMeName, aMeClassID me.ClassID, aMeEntityID uint16,
+	aMeAttributeMask uint16, aMePayload []byte) {
+
+	meAttribMaskStr := strconv.FormatUint(uint64(aMeAttributeMask), 16)
+	attribs := unknownMeAttribs{meAttribMaskStr, hex.EncodeToString(aMePayload)}
+
+	_, ok := OnuDeviceDB.UnknownMeDb[aMeName]
+	if !ok {
+		OnuDeviceDB.UnknownMeDb[aMeName] = make(map[me.ClassID]map[uint16]unknownMeAttribs)
+		OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID] = make(map[uint16]unknownMeAttribs)
+		OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
+	} else {
+		_, ok := OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID]
+		if !ok {
+			OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID] = make(map[uint16]unknownMeAttribs)
+			OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
+		} else {
+			_, ok := OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID][aMeEntityID]
+			if !ok {
+				OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
+			}
 		}
 	}
 }
diff --git a/internal/pkg/mib/mib_sync.go b/internal/pkg/mib/mib_sync.go
index f36cf9d..e5e047d 100755
--- a/internal/pkg/mib/mib_sync.go
+++ b/internal/pkg/mib/mib_sync.go
@@ -542,16 +542,14 @@
 		return
 	}
 	meName := msgObj.ReportedME.GetName()
-	if meName == "UnknownItuG988ManagedEntity" || meName == "UnknownVendorSpecificManagedEntity" {
-		logger.Debugw(ctx, "MibUploadNextResponse Data for unknown ME received - temporary workaround is to ignore it!",
-			log.Fields{"device-id": oo.deviceID, "data-fields": msgObj, "meName": meName})
-	} else {
-		logger.Debugw(ctx, "MibUploadNextResponse Data for:",
-			log.Fields{"device-id": oo.deviceID, "meName": meName, "data-fields": msgObj})
-		meClassID := msgObj.ReportedME.GetClassID()
-		meEntityID := msgObj.ReportedME.GetEntityID()
-		meAttributes := msgObj.ReportedME.GetAttributeValueMap()
+	meClassID := msgObj.ReportedME.GetClassID()
+	meEntityID := msgObj.ReportedME.GetEntityID()
 
+	logger.Debugw(ctx, "MibUploadNextResponse Data for:", log.Fields{"device-id": oo.deviceID, "meName": meName, "data-fields": msgObj})
+
+	if meName == devdb.CUnknownItuG988ManagedEntity || meName == devdb.CUnknownVendorSpecificManagedEntity {
+		oo.pOnuDB.PutUnknownMe(ctx, devdb.UnknownMeName(meName), meClassID, meEntityID, msgObj.ReportedME.GetAttributeMask(), msgObj.BaseLayer.Payload)
+	} else {
 		//with relaxed decoding set in the OMCI-LIB we have the chance to detect if there are some unknown attributes appended which we cannot decode
 		if unknownAttrLayer := (*msg.OmciPacket).Layer(omci.LayerTypeUnknownAttributes); unknownAttrLayer != nil {
 			logger.Warnw(ctx, "MibUploadNextResponse contains unknown attributes", log.Fields{"device-id": oo.deviceID})
@@ -572,8 +570,7 @@
 				logger.Errorw(ctx, "unknownAttrLayer could not be decoded", log.Fields{"device-id": oo.deviceID})
 			}
 		}
-
-		oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, meAttributes)
+		oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, msgObj.ReportedME.GetAttributeValueMap())
 	}
 	if oo.PDevOmciCC.UploadSequNo < oo.PDevOmciCC.UploadNoOfCmds {
 		_ = oo.PDevOmciCC.SendMibUploadNext(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), true)
@@ -934,6 +931,10 @@
 		secondLevelMap["ClassId"] = classID
 		templateMap[classID] = secondLevelMap
 	}
+	unknownMeMap := oo.pOnuDB.UnknownMeDb
+	for unknownMeMapKey := range unknownMeMap {
+		templateMap[string(unknownMeMapKey)] = unknownMeMap[unknownMeMapKey]
+	}
 	mibTemplate, err := json.Marshal(&templateMap)
 	if err != nil {
 		logger.Errorw(ctx, "MibSync - MibTemplate - Failed to marshal mibTemplate", log.Fields{"error": err, "device-id": oo.deviceID})