[VOL-4688] openonuAdapterGo: OMCI extended message set - derive the capability from the OMCC version
Do not merge before https://gerrit.opencord.org/c/bbsim/+/32128

Change-Id: I800f1bae3b696f320c63c80336a22f187b9c947c
diff --git a/internal/pkg/mib/mib_sync.go b/internal/pkg/mib/mib_sync.go
index ea91efb..dc1f35d 100755
--- a/internal/pkg/mib/mib_sync.go
+++ b/internal/pkg/mib/mib_sync.go
@@ -37,6 +37,7 @@
 	"github.com/opencord/voltha-lib-go/v7/pkg/log"
 	cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
 	devdb "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/devdb"
+	otst "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/omcitst"
 	"github.com/opencord/voltha-protos/v5/go/inter_adapter"
 )
 
@@ -68,6 +69,26 @@
 	// 347 // definitions for ME "IPv6 host config data" are currently missing in omci-lib-go!
 }
 
+var omccVersionSupportsExtendedOmciFormat = map[uint8]bool{
+	0x80: false,
+	0x81: false,
+	0x82: false,
+	0x83: false,
+	0x84: false,
+	0x85: false,
+	0x86: false,
+	0xA0: false,
+	0xA1: false,
+	0xA2: false,
+	0xA3: false,
+	0x96: true,
+	0xB0: true,
+	0xB1: true,
+	0xB2: true,
+	0xB3: true,
+	0xB4: true,
+}
+
 var fsmMsg cmn.TestMessageType
 
 func (oo *OnuDeviceEntry) enterStartingState(ctx context.Context, e *fsm.Event) {
@@ -99,7 +120,8 @@
 	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting VendorId and SerialNumber in State": e.FSM.Current(), "device-id": oo.deviceID})
 	requestedAttributes := me.AttributeValueMap{me.OnuG_VendorId: "", me.OnuG_SerialNumber: 0}
 	oo.mutexLastTxParamStruct.Lock()
-	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.OnuGClassID, cmn.OnugMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
+	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.OnuGClassID, cmn.OnugMeID, requestedAttributes,
+		oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
 	//accept also nil as (error) return value for writing to LastTx
 	//  - this avoids misinterpretation of new received OMCI messages
 	if err != nil {
@@ -118,11 +140,12 @@
 	oo.mutexLastTxParamStruct.Unlock()
 }
 
-func (oo *OnuDeviceEntry) enterGettingEquipmentIDState(ctx context.Context, e *fsm.Event) {
-	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting EquipmentId in State": e.FSM.Current(), "device-id": oo.deviceID})
-	requestedAttributes := me.AttributeValueMap{me.Onu2G_EquipmentId: ""}
+func (oo *OnuDeviceEntry) enterGettingEquipIDAndOmccVersState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting EquipmentId and OMCC version in State": e.FSM.Current(), "device-id": oo.deviceID})
+	requestedAttributes := me.AttributeValueMap{me.Onu2G_EquipmentId: "", me.Onu2G_OpticalNetworkUnitManagementAndControlChannelOmccVersion: 0}
 	oo.mutexLastTxParamStruct.Lock()
-	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.Onu2GClassID, cmn.Onu2gMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
+	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.Onu2GClassID, cmn.Onu2gMeID, requestedAttributes,
+		oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
 	//accept also nil as (error) return value for writing to LastTx
 	//  - this avoids misinterpretation of new received OMCI messages
 	if err != nil {
@@ -141,11 +164,44 @@
 	oo.mutexLastTxParamStruct.Unlock()
 }
 
+func (oo *OnuDeviceEntry) enterTestingExtOmciSupportState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start testing extended OMCI msg in State": e.FSM.Current(), "device-id": oo.deviceID})
+	omciVerify := otst.NewOmciTestRequest(log.WithSpanFromContext(context.TODO(), ctx),
+		oo.deviceID, oo.PDevOmciCC, true, true, true)
+	verifyExec := make(chan bool)
+	omciVerify.PerformOmciTest(log.WithSpanFromContext(context.TODO(), ctx), verifyExec)
+
+	// If verification of test message in extended OMCI format fails, reset ONU capability to OMCI baseline format
+	select {
+	case <-time.After(((cmn.CDefaultRetries+1)*otst.CTestRequestOmciTimeout + 1) * time.Second):
+		logger.Warnw(ctx, "testing extended OMCI msg format timed out - reset to baseline format", log.Fields{"device-id": oo.deviceID})
+		oo.MutexPersOnuConfig.Lock()
+		oo.SOnuPersistentData.PersIsExtOmciSupported = false
+		oo.MutexPersOnuConfig.Unlock()
+	case success := <-verifyExec:
+		if success {
+			logger.Debugw(ctx, "testing extended OMCI msg format succeeded", log.Fields{"device-id": oo.deviceID})
+		} else {
+			logger.Warnw(ctx, "testing extended OMCI msg format failed - reset to baseline format", log.Fields{"device-id": oo.deviceID, "result": success})
+			oo.MutexPersOnuConfig.Lock()
+			oo.SOnuPersistentData.PersIsExtOmciSupported = false
+			oo.MutexPersOnuConfig.Unlock()
+		}
+	}
+	pMibUlFsm := oo.PMibUploadFsm
+	if pMibUlFsm != nil {
+		go func(a_pAFsm *cmn.AdapterFsm) {
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvGetFirstSwVersion)
+		}(pMibUlFsm)
+	}
+}
+
 func (oo *OnuDeviceEntry) enterGettingFirstSwVersionState(ctx context.Context, e *fsm.Event) {
 	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting IsActive and Version of first SW-image in State": e.FSM.Current(), "device-id": oo.deviceID})
 	requestedAttributes := me.AttributeValueMap{me.SoftwareImage_IsCommitted: 0, me.SoftwareImage_IsActive: 0, me.SoftwareImage_Version: ""}
 	oo.mutexLastTxParamStruct.Lock()
-	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, cmn.FirstSwImageMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
+	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, cmn.FirstSwImageMeID, requestedAttributes,
+		oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
 	//accept also nil as (error) return value for writing to LastTx
 	//  - this avoids misinterpretation of new received OMCI messages
 	if err != nil {
@@ -168,7 +224,8 @@
 	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting IsActive and Version of second SW-image in State": e.FSM.Current(), "device-id": oo.deviceID})
 	requestedAttributes := me.AttributeValueMap{me.SoftwareImage_IsCommitted: 0, me.SoftwareImage_IsActive: 0, me.SoftwareImage_Version: ""}
 	oo.mutexLastTxParamStruct.Lock()
-	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, cmn.SecondSwImageMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
+	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, cmn.SecondSwImageMeID, requestedAttributes,
+		oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
 	//accept also nil as (error) return value for writing to LastTx
 	//  - this avoids misinterpretation of new received OMCI messages
 	if err != nil {
@@ -191,7 +248,8 @@
 	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting MacAddress in State": e.FSM.Current(), "device-id": oo.deviceID})
 	requestedAttributes := me.AttributeValueMap{me.IpHostConfigData_MacAddress: ""}
 	oo.mutexLastTxParamStruct.Lock()
-	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.IpHostConfigDataClassID, cmn.IPHostConfigDataMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
+	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.IpHostConfigDataClassID, cmn.IPHostConfigDataMeID, requestedAttributes,
+		oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
 	//accept also nil as (error) return value for writing to LastTx
 	//  - this avoids misinterpretation of new received OMCI messages
 	if err != nil {
@@ -605,7 +663,8 @@
 						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})
-						oo.pOnuDB.PutUnknownMeOrAttrib(ctx, devdb.CUnknownAttributesManagedEntity, unknown.EntityClass, unknown.EntityInstance, unknown.AttributeMask, unknown.AttributeData)
+						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})
@@ -729,7 +788,7 @@
 					return fmt.Errorf("mibSync FSM - mandatory attribute SerialNumber not present in OnuG instance - handling of MibSyncChan stopped: %s", oo.deviceID)
 				}
 				// trigger retrieval of EquipmentId
-				_ = oo.PMibUploadFsm.PFsm.Event(UlEvGetEquipmentID)
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvGetEquipIDAndOmcc)
 				return nil
 			case "Onu2G":
 				oo.mutexLastTxParamStruct.RUnlock()
@@ -750,6 +809,34 @@
 					"onuDeviceEntry.equipmentID": oo.SOnuPersistentData.PersEquipmentID})
 				oo.MutexPersOnuConfig.Unlock()
 
+				var omccVersion uint8
+				if onu2GOmccVersion, ok := meAttributes[me.Onu2G_OpticalNetworkUnitManagementAndControlChannelOmccVersion]; ok {
+					oo.MutexPersOnuConfig.Lock()
+					omccVersion = onu2GOmccVersion.(uint8)
+					if _, ok := omccVersionSupportsExtendedOmciFormat[omccVersion]; ok {
+						oo.SOnuPersistentData.PersIsExtOmciSupported = omccVersionSupportsExtendedOmciFormat[omccVersion]
+					} else {
+						logger.Infow(ctx, "MibSync FSM - unknown OMCC version in Onu2G instance - disable extended OMCI support",
+							log.Fields{"device-id": oo.deviceID})
+						oo.SOnuPersistentData.PersIsExtOmciSupported = false
+					}
+					logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu2-G - OMCC version", log.Fields{"device-id": oo.deviceID,
+						"omccVersion": omccVersion, "isExtOmciSupported": oo.SOnuPersistentData.PersIsExtOmciSupported})
+					oo.MutexPersOnuConfig.Unlock()
+				} else {
+					logger.Errorw(ctx, "MibSync FSM - mandatory attribute OMCC version not present in Onu2G instance - handling of MibSyncChan stopped!",
+						log.Fields{"device-id": oo.deviceID})
+					_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+					return fmt.Errorf("mibSync FSM - mandatory attribute OMCC version not present in Onu2G instance - handling of MibSyncChan stopped: %s", oo.deviceID)
+				}
+				oo.MutexPersOnuConfig.RLock()
+				if oo.SOnuPersistentData.PersIsExtOmciSupported {
+					oo.MutexPersOnuConfig.RUnlock()
+					// trigger test of OMCI extended msg format
+					_ = oo.PMibUploadFsm.PFsm.Event(UlEvTestExtOmciSupport)
+					return nil
+				}
+				oo.MutexPersOnuConfig.RUnlock()
 				// trigger retrieval of 1st SW-image info
 				_ = oo.PMibUploadFsm.PFsm.Event(UlEvGetFirstSwVersion)
 				return nil
diff --git a/internal/pkg/mib/onu_device_entry.go b/internal/pkg/mib/onu_device_entry.go
index 9014283..51f1cd3 100755
--- a/internal/pkg/mib/onu_device_entry.go
+++ b/internal/pkg/mib/onu_device_entry.go
@@ -48,7 +48,8 @@
 	UlEvStart              = "UlEvStart"
 	UlEvResetMib           = "UlEvResetMib"
 	UlEvGetVendorAndSerial = "UlEvGetVendorAndSerial"
-	UlEvGetEquipmentID     = "UlEvGetEquipmentId"
+	UlEvGetEquipIDAndOmcc  = "UlEvGetEquipIDAndOmcc"
+	UlEvTestExtOmciSupport = "UlEvTestExtOmciSupport"
 	UlEvGetFirstSwVersion  = "UlEvGetFirstSwVersion"
 	UlEvGetSecondSwVersion = "UlEvGetSecondSwVersion"
 	UlEvGetMacAddress      = "UlEvGetMacAddress"
@@ -71,7 +72,8 @@
 	UlStStarting               = "UlStStarting"
 	UlStResettingMib           = "UlStResettingMib"
 	UlStGettingVendorAndSerial = "UlStGettingVendorAndSerial"
-	UlStGettingEquipmentID     = "UlStGettingEquipmentID"
+	UlStGettingEquipIDAndOmcc  = "UlStGettingEquipIDAndOmcc"
+	UlStTestingExtOmciSupport  = "UlStTestingExtOmciSupport"
 	UlStGettingFirstSwVersion  = "UlStGettingFirstSwVersion"
 	UlStGettingSecondSwVersion = "UlStGettingSecondSwVersion"
 	UlStGettingMacAddress      = "UlStGettingMacAddress"
@@ -143,6 +145,7 @@
 	PersMacAddress         string            `json:"mac_address"`
 	PersVendorID           string            `json:"vendor_id"`
 	PersEquipmentID        string            `json:"equipment_id"`
+	PersIsExtOmciSupported bool              `json:"is_ext_omci_supported"`
 	PersActiveSwVersion    string            `json:"active_sw_version"`
 	PersAdminState         string            `json:"admin_state"`
 	PersOperState          string            `json:"oper_state"`
@@ -292,8 +295,9 @@
 
 			{Name: UlEvResetMib, Src: []string{UlStStarting}, Dst: UlStResettingMib},
 			{Name: UlEvGetVendorAndSerial, Src: []string{UlStResettingMib}, Dst: UlStGettingVendorAndSerial},
-			{Name: UlEvGetEquipmentID, Src: []string{UlStGettingVendorAndSerial}, Dst: UlStGettingEquipmentID},
-			{Name: UlEvGetFirstSwVersion, Src: []string{UlStGettingEquipmentID}, Dst: UlStGettingFirstSwVersion},
+			{Name: UlEvGetEquipIDAndOmcc, Src: []string{UlStGettingVendorAndSerial}, Dst: UlStGettingEquipIDAndOmcc},
+			{Name: UlEvTestExtOmciSupport, Src: []string{UlStGettingEquipIDAndOmcc}, Dst: UlStTestingExtOmciSupport},
+			{Name: UlEvGetFirstSwVersion, Src: []string{UlStGettingEquipIDAndOmcc, UlStTestingExtOmciSupport}, Dst: UlStGettingFirstSwVersion},
 			{Name: UlEvGetSecondSwVersion, Src: []string{UlStGettingFirstSwVersion}, Dst: UlStGettingSecondSwVersion},
 			{Name: UlEvGetMacAddress, Src: []string{UlStGettingSecondSwVersion}, Dst: UlStGettingMacAddress},
 			{Name: UlEvGetMibTemplate, Src: []string{UlStGettingMacAddress}, Dst: UlStGettingMibTemplate},
@@ -333,13 +337,13 @@
 			{Name: UlEvSuccess, Src: []string{UlStResynchronizing}, Dst: UlStInSync},
 			{Name: UlEvDiffsFound, Src: []string{UlStResynchronizing}, Dst: UlStOutOfSync},
 
-			{Name: UlEvTimeout, Src: []string{UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipmentID, UlStGettingFirstSwVersion,
-				UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing, UlStVerifyingAndStoringTPs,
-				UlStExaminingMds, UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStStarting},
+			{Name: UlEvTimeout, Src: []string{UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipIDAndOmcc, UlStTestingExtOmciSupport,
+				UlStGettingFirstSwVersion, UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing,
+				UlStVerifyingAndStoringTPs, UlStExaminingMds, UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStStarting},
 
-			{Name: UlEvStop, Src: []string{UlStStarting, UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipmentID, UlStGettingFirstSwVersion,
-				UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing, UlStVerifyingAndStoringTPs,
-				UlStExaminingMds, UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStDisabled},
+			{Name: UlEvStop, Src: []string{UlStStarting, UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipIDAndOmcc, UlStTestingExtOmciSupport,
+				UlStGettingFirstSwVersion, UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing,
+				UlStVerifyingAndStoringTPs, UlStExaminingMds, UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStDisabled},
 		},
 
 		fsm.Callbacks{
@@ -347,7 +351,8 @@
 			"enter_" + UlStStarting:               func(e *fsm.Event) { onuDeviceEntry.enterStartingState(ctx, e) },
 			"enter_" + UlStResettingMib:           func(e *fsm.Event) { onuDeviceEntry.enterResettingMibState(ctx, e) },
 			"enter_" + UlStGettingVendorAndSerial: func(e *fsm.Event) { onuDeviceEntry.enterGettingVendorAndSerialState(ctx, e) },
-			"enter_" + UlStGettingEquipmentID:     func(e *fsm.Event) { onuDeviceEntry.enterGettingEquipmentIDState(ctx, e) },
+			"enter_" + UlStGettingEquipIDAndOmcc:  func(e *fsm.Event) { onuDeviceEntry.enterGettingEquipIDAndOmccVersState(ctx, e) },
+			"enter_" + UlStTestingExtOmciSupport:  func(e *fsm.Event) { onuDeviceEntry.enterTestingExtOmciSupportState(ctx, e) },
 			"enter_" + UlStGettingFirstSwVersion:  func(e *fsm.Event) { onuDeviceEntry.enterGettingFirstSwVersionState(ctx, e) },
 			"enter_" + UlStGettingSecondSwVersion: func(e *fsm.Event) { onuDeviceEntry.enterGettingSecondSwVersionState(ctx, e) },
 			"enter_" + UlStGettingMacAddress:      func(e *fsm.Event) { onuDeviceEntry.enterGettingMacAddressState(ctx, e) },
@@ -533,7 +538,7 @@
 	oo.MutexPersOnuConfig.Lock()
 	defer oo.MutexPersOnuConfig.Unlock()
 	oo.SOnuPersistentData =
-		onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
+		onuPersistentData{0, 0, "", "", "", "", false, "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
 	oo.mutexOnuKVStore.RLock()
 	Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
 	oo.mutexOnuKVStore.RUnlock()
@@ -588,7 +593,7 @@
 
 	oo.SOnuPersistentData.PersUniConfig = nil //releasing all UniConfig entries to garbage collector default entry
 	oo.SOnuPersistentData =
-		onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
+		onuPersistentData{0, 0, "", "", "", "", false, "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
 	logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
 	oo.mutexOnuKVStore.Lock()
 	err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)