[VOL-4664] openonuAdapterGo: Store OMCI unknown attributes in MIB template

Change-Id: I5a38a4f67da23f4718245bfd490362c9969e68a9
diff --git a/VERSION b/VERSION
index 473593f..37be771 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.2-dev275
+2.2.2-dev276
diff --git a/internal/pkg/devdb/onu_device_db.go b/internal/pkg/devdb/onu_device_db.go
index d3338c8..627d31c 100755
--- a/internal/pkg/devdb/onu_device_db.go
+++ b/internal/pkg/devdb/onu_device_db.go
@@ -23,7 +23,6 @@
 	"fmt"
 	"reflect"
 	"sort"
-	"strconv"
 	"sync"
 
 	me "github.com/opencord/omci-lib-go/v2/generated"
@@ -32,28 +31,32 @@
 
 type meDbMap map[me.ClassID]map[uint16]me.AttributeValueMap
 
-// UnknownMeName type to be used for unknown ME names
-type UnknownMeName string
+// UnknownMeOrAttribName type to be used for unknown ME and attribute names
+type UnknownMeOrAttribName string
 
-// allowed values for type UnknownMeName
+// names for unknown ME and attribute identifiers
 const (
 	CUnknownItuG988ManagedEntity        = "UnknownItuG988ManagedEntity"
 	CUnknownVendorSpecificManagedEntity = "UnknownVendorSpecificManagedEntity"
+	CUnknownAttributesManagedEntity     = "UnknownAttributesManagedEntity"
 )
 
-type unknownMeAttribs struct {
+// CStartUnknownMeAttribsInBaseLayerPayload defines start of unknown ME attribs after ClassID, InstanceID and AttribMask
+const CStartUnknownMeAttribsInBaseLayerPayload = 6
+
+type unknownAttribs struct {
 	AttribMask  string `json:"AttributeMask"`
 	AttribBytes string `json:"AttributeBytes"`
 }
-type unknownMeDbMap map[UnknownMeName]map[me.ClassID]map[uint16]unknownMeAttribs
+type unknownMeAndAttribDbMap map[UnknownMeOrAttribName]map[me.ClassID]map[uint16]unknownAttribs
 
 //OnuDeviceDB structure holds information about ME's
 type OnuDeviceDB struct {
-	ctx         context.Context
-	deviceID    string
-	MeDb        meDbMap
-	meDbLock    sync.RWMutex
-	UnknownMeDb unknownMeDbMap
+	ctx                  context.Context
+	deviceID             string
+	MeDb                 meDbMap
+	meDbLock             sync.RWMutex
+	UnknownMeAndAttribDb unknownMeAndAttribDbMap
 }
 
 //NewOnuDeviceDB returns a new instance for a specific ONU_Device_Entry
@@ -63,7 +66,7 @@
 	OnuDeviceDB.ctx = ctx
 	OnuDeviceDB.deviceID = aDeviceID
 	OnuDeviceDB.MeDb = make(meDbMap)
-	OnuDeviceDB.UnknownMeDb = make(unknownMeDbMap)
+	OnuDeviceDB.UnknownMeAndAttribDb = make(unknownMeAndAttribDbMap)
 
 	return &OnuDeviceDB
 }
@@ -166,27 +169,27 @@
 	}
 }
 
-//PutUnknownMe puts an unknown ME instance into internal ONU DB
-func (OnuDeviceDB *OnuDeviceDB) PutUnknownMe(ctx context.Context, aMeName UnknownMeName, aMeClassID me.ClassID, aMeEntityID uint16,
+//PutUnknownMeOrAttrib puts an instance with unknown ME or attributes into internal ONU DB
+func (OnuDeviceDB *OnuDeviceDB) PutUnknownMeOrAttrib(ctx context.Context, aMeName UnknownMeOrAttribName, aMeClassID me.ClassID, aMeEntityID uint16,
 	aMeAttributeMask uint16, aMePayload []byte) {
 
-	meAttribMaskStr := strconv.FormatUint(uint64(aMeAttributeMask), 16)
-	attribs := unknownMeAttribs{meAttribMaskStr, hex.EncodeToString(aMePayload)}
+	meAttribMaskStr := fmt.Sprintf("0x%04x", aMeAttributeMask)
+	attribs := unknownAttribs{meAttribMaskStr, hex.EncodeToString(aMePayload)}
 
-	_, ok := OnuDeviceDB.UnknownMeDb[aMeName]
+	_, ok := OnuDeviceDB.UnknownMeAndAttribDb[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
+		OnuDeviceDB.UnknownMeAndAttribDb[aMeName] = make(map[me.ClassID]map[uint16]unknownAttribs)
+		OnuDeviceDB.UnknownMeAndAttribDb[aMeName][aMeClassID] = make(map[uint16]unknownAttribs)
+		OnuDeviceDB.UnknownMeAndAttribDb[aMeName][aMeClassID][aMeEntityID] = attribs
 	} else {
-		_, ok := OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID]
+		_, ok := OnuDeviceDB.UnknownMeAndAttribDb[aMeName][aMeClassID]
 		if !ok {
-			OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID] = make(map[uint16]unknownMeAttribs)
-			OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
+			OnuDeviceDB.UnknownMeAndAttribDb[aMeName][aMeClassID] = make(map[uint16]unknownAttribs)
+			OnuDeviceDB.UnknownMeAndAttribDb[aMeName][aMeClassID][aMeEntityID] = attribs
 		} else {
-			_, ok := OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID][aMeEntityID]
+			_, ok := OnuDeviceDB.UnknownMeAndAttribDb[aMeName][aMeClassID][aMeEntityID]
 			if !ok {
-				OnuDeviceDB.UnknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
+				OnuDeviceDB.UnknownMeAndAttribDb[aMeName][aMeClassID][aMeEntityID] = attribs
 			}
 		}
 	}
diff --git a/internal/pkg/mib/mib_sync.go b/internal/pkg/mib/mib_sync.go
index c839d45..3945c45 100755
--- a/internal/pkg/mib/mib_sync.go
+++ b/internal/pkg/mib/mib_sync.go
@@ -586,7 +586,11 @@
 		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)
+			logger.Debugw(ctx, "MibUploadNextResponse contains unknown ME", log.Fields{"device-id": oo.deviceID,
+				"Me-Name": devdb.UnknownMeOrAttribName(meName), "Me-ClassId": meClassID, "Me-InstId": meEntityID,
+				"unknown mask": msgObj.ReportedME.GetAttributeMask(), "unknown attributes": msgObj.BaseLayer.Payload})
+			oo.pOnuDB.PutUnknownMeOrAttrib(ctx, devdb.UnknownMeOrAttribName(meName), meClassID, meEntityID,
+				msgObj.ReportedME.GetAttributeMask(), msgObj.BaseLayer.Payload[devdb.CStartUnknownMeAttribsInBaseLayerPayload:])
 		} 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 {
@@ -601,8 +605,7 @@
 						logger.Warnw(ctx, "unknown attributes detected for", log.Fields{"device-id": oo.deviceID,
 							"Me-ClassId": unknownAttrClassID, "Me-InstId": unknownAttrInst, "unknown mask": unknownAttrMask,
 							"unknown attributes": unknownAttrBlob})
-						//TODO!!! We have to find a way to put this extra information into the (MIB)DB, see below pOnuDB.PutMe
-						//  this probably requires an (add-on) extension in the DB, that should not harm any other (get) processing -> later as a second step
+						oo.pOnuDB.PutUnknownMeOrAttrib(ctx, devdb.CUnknownAttributesManagedEntity, unknown.EntityClass, unknown.EntityInstance, unknown.AttributeMask, unknown.AttributeData)
 					} // for all included ME's with unknown attributes
 				} else {
 					logger.Errorw(ctx, "unknownAttrLayer could not be decoded", log.Fields{"device-id": oo.deviceID})
@@ -1051,9 +1054,9 @@
 		secondLevelMap["ClassId"] = classID
 		templateMap[classID] = secondLevelMap
 	}
-	unknownMeMap := oo.pOnuDB.UnknownMeDb
-	for unknownMeMapKey := range unknownMeMap {
-		templateMap[string(unknownMeMapKey)] = unknownMeMap[unknownMeMapKey]
+	unknownMeAndAttribMap := oo.pOnuDB.UnknownMeAndAttribDb
+	for unknownMeAndAttribMapKey := range unknownMeAndAttribMap {
+		templateMap[string(unknownMeAndAttribMapKey)] = unknownMeAndAttribMap[unknownMeAndAttribMapKey]
 	}
 	mibTemplate, err := json.Marshal(&templateMap)
 	if err != nil {