[VOL-3380] Functional area specific logging
Change-Id: I67414da013d8fc82827fcdb69d4f8a34040625d3
diff --git a/internal/pkg/mib/common.go b/internal/pkg/mib/common.go
new file mode 100755
index 0000000..e9d39c3
--- /dev/null
+++ b/internal/pkg/mib/common.go
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+)
+
+var logger log.CLogger
+
+func init() {
+ // Setup this package so that it's log level can be modified at run time
+ var err error
+ logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "mib"})
+ if err != nil {
+ panic(err)
+ }
+}
diff --git a/internal/pkg/mib/mib_download.go b/internal/pkg/mib/mib_download.go
new file mode 100755
index 0000000..9c49f9b
--- /dev/null
+++ b/internal/pkg/mib/mib_download.go
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/looplab/fsm"
+
+ "github.com/opencord/omci-lib-go"
+ me "github.com/opencord/omci-lib-go/generated"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ //ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+ //"github.com/opencord/voltha-protos/v5/go/openflow_13"
+ //"github.com/opencord/voltha-protos/v5/go/voltha"
+ cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
+)
+
+func (onuDeviceEntry *OnuDeviceEntry) enterDLStartingState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibDownload FSM", log.Fields{"Start downloading OMCI MIB in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ // in case the used channel is not yet defined (can be re-used after restarts)
+ if onuDeviceEntry.omciMessageReceived == nil {
+ onuDeviceEntry.omciMessageReceived = make(chan bool)
+ logger.Debug(ctx, "MibDownload FSM - defining the BridgeInit RxChannel")
+ }
+ // start go routine for processing of MibDownload messages
+ go onuDeviceEntry.processMibDownloadMessages(ctx)
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterCreatingGalState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibDownload FSM", log.Fields{"Tx create::GAL Ethernet Profile in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+ meInstance, err := onuDeviceEntry.PDevOmciCC.SendCreateGalEthernetProfile(log.WithSpanFromContext(context.TODO(), ctx),
+ onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ if err != nil {
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ logger.Errorw(ctx, "GalEthernetProfile create failed, aborting MibDownload FSM!",
+ log.Fields{"device-id": onuDeviceEntry.deviceID})
+ pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+ if pMibDlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = a_pAFsm.PFsm.Event(DlEvReset)
+ }(pMibDlFsm)
+ }
+ return
+ }
+ onuDeviceEntry.pLastTxMeInstance = meInstance
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterSettingOnu2gState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibDownload FSM", log.Fields{"Tx Set::ONU2-G in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+ meInstance, err := onuDeviceEntry.PDevOmciCC.SendSetOnu2g(log.WithSpanFromContext(context.TODO(), ctx),
+ onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ if err != nil {
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ logger.Errorw(ctx, "ONU2-G set failed, aborting MibDownload FSM!",
+ log.Fields{"device-id": onuDeviceEntry.deviceID})
+ pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+ if pMibDlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = a_pAFsm.PFsm.Event(DlEvReset)
+ }(pMibDlFsm)
+ }
+ return
+ }
+ onuDeviceEntry.pLastTxMeInstance = meInstance
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterBridgeInitState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibDownload FSM - starting bridge config port loop", log.Fields{
+ "in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ go onuDeviceEntry.performInitialBridgeSetup(ctx)
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterDownloadedState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibDownload FSM", log.Fields{"send notification to core in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.transferSystemEvent(ctx, cmn.MibDownloadDone)
+ //let's reset the state machine in order to release all resources now
+ pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+ if pMibDlFsm != nil {
+ // obviously calling some FSM event here directly does not work - so trying to decouple it ...
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ if a_pAFsm != nil && a_pAFsm.PFsm != nil {
+ _ = a_pAFsm.PFsm.Event(DlEvReset)
+ }
+ }(pMibDlFsm)
+ }
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterResettingState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibDownload FSM resetting", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+ if pMibDlFsm != nil {
+ // abort running message processing
+ fsmAbortMsg := cmn.Message{
+ Type: cmn.TestMsg,
+ Data: cmn.TestMessage{
+ TestMessageVal: cmn.AbortMessageProcessing,
+ },
+ }
+ pMibDlFsm.CommChan <- fsmAbortMsg
+
+ //try to restart the FSM to 'disabled'
+ // see DownloadedState: decouple event transfer
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ if a_pAFsm != nil && a_pAFsm.PFsm != nil {
+ _ = a_pAFsm.PFsm.Event(DlEvRestart)
+ }
+ }(pMibDlFsm)
+ }
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) processMibDownloadMessages(ctx context.Context) {
+ logger.Debugw(ctx, "Start MibDownload Msg processing", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+loop:
+ for {
+ // case <-ctx.Done():
+ // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": onuDeviceEntry.deviceID})
+ // break loop
+ // unless multiple channels are not involved, we should not use select
+ message, ok := <-onuDeviceEntry.PMibDownloadFsm.CommChan
+ if !ok {
+ logger.Info(ctx, "MibDownload Rx Msg", log.Fields{"Message couldn't be read from channel for device-id": onuDeviceEntry.deviceID})
+ // but then we have to ensure a restart of the FSM as well - as exceptional procedure
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvRestart)
+ break loop
+ }
+ logger.Debugw(ctx, "MibDownload Rx Msg", log.Fields{"Received message for device-id": onuDeviceEntry.deviceID})
+
+ switch message.Type {
+ case cmn.TestMsg:
+ msg, _ := message.Data.(cmn.TestMessage)
+ if msg.TestMessageVal == cmn.AbortMessageProcessing {
+ logger.Debugw(ctx, "MibDownload abort ProcessMsg", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+ break loop
+ }
+ logger.Warnw(ctx, "MibDownload unknown TestMessage", log.Fields{"device-id": onuDeviceEntry.deviceID, "MessageVal": msg.TestMessageVal})
+ case cmn.OMCI:
+ msg, _ := message.Data.(cmn.OmciMessage)
+ onuDeviceEntry.handleOmciMibDownloadMessage(ctx, msg)
+ default:
+ logger.Warn(ctx, "MibDownload Rx Msg", log.Fields{"Unknown message type received for device-id": onuDeviceEntry.deviceID,
+ "message.Type": message.Type})
+ }
+
+ }
+ logger.Debugw(ctx, "End MibDownload Msg processing", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) handleOmciMibDownloadCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.CreateResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success && msgObj.Result != me.InstanceExists {
+ logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": onuDeviceEntry.deviceID, "Error": msgObj.Result})
+ // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ return
+ }
+ // maybe there is a way of pushing the specific create response type generally to the FSM
+ // and let the FSM verify, if the response was according to current state
+ // and possibly store the element to DB and progress - maybe some future option ...
+ // but as that is not straightforward to me I insert the type checkes manually here
+ // and feed the FSM with only 'pre-defined' events ...
+
+ onuDeviceEntry.mutexPLastTxMeInstance.RLock()
+ if onuDeviceEntry.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == onuDeviceEntry.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == onuDeviceEntry.pLastTxMeInstance.GetEntityID() {
+ //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
+ // if, then something like:
+ //onuDeviceEntry.pOnuDB.StoreMe(msgObj)
+
+ // maybe we can use just the same eventName for different state transitions like "forward"
+ // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
+ switch onuDeviceEntry.pLastTxMeInstance.GetName() {
+ case "GalEthernetProfile":
+ { // let the FSM proceed ...
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvRxGalResp)
+ }
+ case "MacBridgeServiceProfile",
+ "MacBridgePortConfigurationData",
+ "ExtendedVlanTaggingOperationConfigurationData":
+ { // let bridge init proceed by stopping the wait function
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ onuDeviceEntry.omciMessageReceived <- true
+ }
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": onuDeviceEntry.pLastTxMeInstance.GetName(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ }
+ }
+ } else {
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ }
+ } else {
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ logger.Errorw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ }
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) handleOmciMibDownloadSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected for SetResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.SetResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned for SetResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ logger.Debugw(ctx, "SetResponse Data", log.Fields{"device-id": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success {
+ logger.Errorw(ctx, "Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": onuDeviceEntry.deviceID,
+ "Error": msgObj.Result})
+ // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ return
+ }
+ // compare comments above for CreateResponse (apply also here ...)
+
+ onuDeviceEntry.mutexPLastTxMeInstance.RLock()
+ if onuDeviceEntry.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == onuDeviceEntry.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == onuDeviceEntry.pLastTxMeInstance.GetEntityID() {
+ //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
+ // if, then something like:
+ //onuDeviceEntry.pOnuDB.StoreMe(msgObj)
+
+ switch onuDeviceEntry.pLastTxMeInstance.GetName() {
+ case "Onu2G":
+ { // let the FSM proceed ...
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvRxOnu2gResp)
+ }
+ //so far that was the only MibDownlad Set Element ...
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": onuDeviceEntry.pLastTxMeInstance.GetName(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ }
+
+ }
+ } else {
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ }
+ } else {
+ onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+ logger.Errorw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ }
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) handleOmciMibDownloadMessage(ctx context.Context, msg cmn.OmciMessage) {
+ logger.Debugw(ctx, "Rx OMCI MibDownload Msg", log.Fields{"device-id": onuDeviceEntry.deviceID,
+ "msgType": msg.OmciMsg.MessageType})
+
+ switch msg.OmciMsg.MessageType {
+ case omci.CreateResponseType:
+ onuDeviceEntry.handleOmciMibDownloadCreateResponseMessage(ctx, msg)
+ //TODO
+ // onuDeviceEntry.PMibDownloadFsm.PFsm.Event("rx_evtocd_resp")
+ case omci.SetResponseType:
+ onuDeviceEntry.handleOmciMibDownloadSetResponseMessage(ctx, msg)
+ default:
+ {
+ logger.Errorw(ctx, "Rx OMCI MibDownload unhandled MsgType", log.Fields{"device-id": onuDeviceEntry.deviceID,
+ "omciMsgType": msg.OmciMsg.MessageType})
+ return
+ }
+ } // switch msg.OmciMsg.MessageType
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) performInitialBridgeSetup(ctx context.Context) {
+ for uniNo, uniPort := range *onuDeviceEntry.baseDeviceHandler.GetUniEntityMap() {
+ logger.Debugw(ctx, "Starting IntialBridgeSetup", log.Fields{
+ "device-id": onuDeviceEntry.deviceID, "for PortNo": uniNo})
+
+ //create MBSP
+ onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+ meInstance, err := onuDeviceEntry.PDevOmciCC.SendCreateMBServiceProfile(
+ log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+ if err != nil {
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ logger.Errorw(ctx, "MBServiceProfile create failed, aborting MibDownload FSM!", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+ return
+ }
+ onuDeviceEntry.pLastTxMeInstance = meInstance
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ //verify response
+ err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
+ if err != nil {
+ logger.Errorw(ctx, "InitialBridgeSetup failed at MBSP, aborting MIB Download!",
+ log.Fields{"device-id": onuDeviceEntry.deviceID})
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+ return
+ }
+
+ //create MBPCD
+ onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+ meInstance, err = onuDeviceEntry.PDevOmciCC.SendCreateMBPConfigDataUniSide(
+ log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+ if err != nil {
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ logger.Errorw(ctx, "MBPConfigData create failed, aborting MibDownload FSM!",
+ log.Fields{"device-id": onuDeviceEntry.deviceID})
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+ return
+ }
+ onuDeviceEntry.pLastTxMeInstance = meInstance
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ //verify response
+ err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
+ if err != nil {
+ logger.Errorw(ctx, "InitialBridgeSetup failed at MBPCD, aborting MIB Download!",
+ log.Fields{"device-id": onuDeviceEntry.deviceID})
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+ return
+ }
+
+ //create EVTOCD
+ onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+ meInstance, err = onuDeviceEntry.PDevOmciCC.SendCreateEVTOConfigData(
+ log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+ if err != nil {
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ logger.Errorw(ctx, "EVTOConfigData create failed, aborting MibDownload FSM!",
+ log.Fields{"device-id": onuDeviceEntry.deviceID})
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+ return
+ }
+ onuDeviceEntry.pLastTxMeInstance = meInstance
+ onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+ //verify response
+ err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
+ if err != nil {
+ logger.Errorw(ctx, "InitialBridgeSetup failed at EVTOCD, aborting MIB Download!",
+ log.Fields{"device-id": onuDeviceEntry.deviceID})
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+ return
+ }
+ }
+ // if Config has been done for all UNI related instances let the FSM proceed
+ // while we did not check here, if there is some port at all - !?
+ logger.Infow(ctx, "IntialBridgeSetup finished", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ _ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvRxBridgeResp)
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) waitforOmciResponse(ctx context.Context, apMeInstance *me.ManagedEntity) error {
+ select {
+ // maybe be also some outside cancel (but no context modeled for the moment ...)
+ // case <-ctx.Done():
+ // logger.Info("MibDownload-bridge-init message reception canceled", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+ case <-time.After(onuDeviceEntry.PDevOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
+ logger.Warnw(ctx, "MibDownload-bridge-init timeout", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+ return fmt.Errorf("mibDownloadBridgeInit timeout %s", onuDeviceEntry.deviceID)
+ case success := <-onuDeviceEntry.omciMessageReceived:
+ if success {
+ logger.Debug(ctx, "MibDownload-bridge-init response received")
+ return nil
+ }
+ // should not happen so far
+ logger.Warnw(ctx, "MibDownload-bridge-init response error", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+ return fmt.Errorf("mibDownloadBridgeInit responseError %s", onuDeviceEntry.deviceID)
+ }
+}
diff --git a/internal/pkg/mib/mib_sync.go b/internal/pkg/mib/mib_sync.go
new file mode 100755
index 0000000..871b6de
--- /dev/null
+++ b/internal/pkg/mib/mib_sync.go
@@ -0,0 +1,1103 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+ "context"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/looplab/fsm"
+
+ "time"
+
+ "github.com/opencord/omci-lib-go"
+ me "github.com/opencord/omci-lib-go/generated"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
+ "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"
+)
+
+type sLastTxMeParameter struct {
+ lastTxMessageType omci.MessageType
+ pLastTxMeInstance *me.ManagedEntity
+ repeatCount uint8
+}
+
+var supportedClassIds = []me.ClassID{
+ me.CardholderClassID, // 5
+ me.CircuitPackClassID, // 6
+ me.SoftwareImageClassID, // 7
+ me.PhysicalPathTerminationPointEthernetUniClassID, // 11
+ me.PhysicalPathTerminationPointPotsUniClassID, // 53
+ me.OltGClassID, // 131
+ me.OnuPowerSheddingClassID, // 133
+ me.IpHostConfigDataClassID, // 134
+ me.OnuGClassID, // 256
+ me.Onu2GClassID, // 257
+ me.TContClassID, // 262
+ me.AniGClassID, // 263
+ me.UniGClassID, // 264
+ me.PriorityQueueClassID, // 277
+ me.TrafficSchedulerClassID, // 278
+ me.VirtualEthernetInterfacePointClassID, // 329
+ me.EnhancedSecurityControlClassID, // 332
+ me.OnuDynamicPowerManagementControlClassID, // 336
+ // 347 // definitions for ME "IPv6 host config data" are currently missing in omci-lib-go!
+}
+
+var fsmMsg cmn.TestMessageType
+
+func (oo *OnuDeviceEntry) enterStartingState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start processing MibSync-msgs in State": e.FSM.Current(), "device-id": oo.deviceID})
+ oo.pOnuDB = devdb.NewOnuDeviceDB(log.WithSpanFromContext(context.TODO(), ctx), oo.deviceID)
+ go oo.processMibSyncMessages(ctx)
+}
+
+func (oo *OnuDeviceEntry) enterResettingMibState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibTemplate processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+
+ if (!oo.IsNewOnu() && !oo.baseDeviceHandler.IsReconciling()) || //use case: re-auditing failed
+ oo.baseDeviceHandler.IsSkipOnuConfigReconciling() { //use case: reconciling without omci-config failed
+ oo.baseDeviceHandler.PrepareReconcilingWithActiveAdapter(ctx)
+ oo.devState = cmn.DeviceStatusInit
+ }
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"send mibReset in State": e.FSM.Current(), "device-id": oo.deviceID})
+ oo.mutexLastTxParamStruct.Lock()
+ _ = oo.PDevOmciCC.SendMibReset(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), true)
+ //TODO: needs to handle timeouts
+ //even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
+ // that the lastTxMessageType is correctly set to avoid misinterpreting other responses
+ oo.lastTxParamStruct.lastTxMessageType = omci.MibResetRequestType
+ oo.lastTxParamStruct.repeatCount = 0
+ oo.mutexLastTxParamStruct.Unlock()
+}
+
+func (oo *OnuDeviceEntry) enterGettingVendorAndSerialState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting VendorId and SerialNumber in State": e.FSM.Current(), "device-id": oo.deviceID})
+ requestedAttributes := me.AttributeValueMap{"VendorId": "", "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)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
+ logger.Errorw(ctx, "ONU-G get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
+ pMibUlFsm := oo.PMibUploadFsm
+ if pMibUlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ }(pMibUlFsm)
+ }
+ return
+ }
+ oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
+ oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ 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{"EquipmentId": ""}
+ 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)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
+ logger.Errorw(ctx, "ONU2-G get failed, aborting MibSync FSM!", log.Fields{"device-id": oo.deviceID})
+ pMibUlFsm := oo.PMibUploadFsm
+ if pMibUlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ }(pMibUlFsm)
+ }
+ return
+ }
+ oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
+ oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
+}
+
+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{"IsCommitted": 0, "IsActive": 0, "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)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
+ logger.Errorw(ctx, "SoftwareImage get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
+ pMibUlFsm := oo.PMibUploadFsm
+ if pMibUlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ }(pMibUlFsm)
+ }
+ return
+ }
+ oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
+ oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
+}
+
+func (oo *OnuDeviceEntry) enterGettingSecondSwVersionState(ctx context.Context, e *fsm.Event) {
+ 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{"IsCommitted": 0, "IsActive": 0, "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)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
+ logger.Errorw(ctx, "SoftwareImage get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
+ pMibUlFsm := oo.PMibUploadFsm
+ if pMibUlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ }(pMibUlFsm)
+ }
+ return
+ }
+ oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
+ oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
+}
+
+func (oo *OnuDeviceEntry) enterGettingMacAddressState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting MacAddress in State": e.FSM.Current(), "device-id": oo.deviceID})
+ requestedAttributes := me.AttributeValueMap{"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)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
+ logger.Errorw(ctx, "IpHostConfigData get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
+ pMibUlFsm := oo.PMibUploadFsm
+ if pMibUlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ }(pMibUlFsm)
+ }
+ return
+ }
+ oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
+ oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
+}
+
+func (oo *OnuDeviceEntry) enterGettingMibTemplateState(ctx context.Context, e *fsm.Event) {
+
+ oo.mutexOnuSwImageIndications.RLock()
+ if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+ oo.MutexPersOnuConfig.Lock()
+ oo.SOnuPersistentData.PersActiveSwVersion = oo.onuSwImageIndications.ActiveEntityEntry.Version
+ oo.MutexPersOnuConfig.Unlock()
+ oo.mutexOnuSwImageIndications.RUnlock()
+ } else {
+ oo.mutexOnuSwImageIndications.RUnlock()
+ logger.Errorw(ctx, "get-mib-template: no active SW version found, working with empty SW version, which might be untrustworthy",
+ log.Fields{"device-id": oo.deviceID})
+ }
+ if oo.getMibFromTemplate(ctx) {
+ logger.Debug(ctx, "MibSync FSM - valid MEs stored from template")
+ oo.pOnuDB.LogMeDb(ctx)
+ fsmMsg = cmn.LoadMibTemplateOk
+ } else {
+ logger.Debug(ctx, "MibSync FSM - no valid MEs stored from template - perform MIB-upload!")
+ fsmMsg = cmn.LoadMibTemplateFailed
+
+ oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+ if mibTemplateIsGenerated, exist := oo.pOpenOnuAc.GetMibTemplatesGenerated(oo.mibTemplatePath); exist {
+ if mibTemplateIsGenerated {
+ logger.Debugw(ctx,
+ "MibSync FSM - template was successfully generated before, but doesn't exist or isn't usable anymore - reset flag in map",
+ log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, false)
+ }
+ }
+ oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+ }
+ mibSyncMsg := cmn.Message{
+ Type: cmn.TestMsg,
+ Data: cmn.TestMessage{
+ TestMessageVal: fsmMsg,
+ },
+ }
+ oo.PMibUploadFsm.CommChan <- mibSyncMsg
+}
+
+func (oo *OnuDeviceEntry) enterUploadingState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"send MibUpload in State": e.FSM.Current(), "device-id": oo.deviceID})
+ _ = oo.PDevOmciCC.SendMibUpload(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), true)
+ //even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
+ // that the lastTxMessageType is correctly set to avoid misinterpreting other responses
+ oo.mutexLastTxParamStruct.Lock()
+ oo.lastTxParamStruct.lastTxMessageType = omci.MibUploadRequestType
+ oo.mutexLastTxParamStruct.Unlock()
+}
+
+func (oo *OnuDeviceEntry) enterUploadDoneState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"send notification to core in State": e.FSM.Current(), "device-id": oo.deviceID})
+ oo.transferSystemEvent(ctx, cmn.MibDatabaseSync)
+ go func() {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ }()
+}
+
+func (oo *OnuDeviceEntry) enterInSyncState(ctx context.Context, e *fsm.Event) {
+ oo.MutexPersOnuConfig.Lock()
+ oo.SOnuPersistentData.PersMibLastDbSync = uint32(time.Now().Unix())
+ oo.MutexPersOnuConfig.Unlock()
+ if oo.mibAuditInterval > 0 {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"trigger next Audit in State": e.FSM.Current(), "oo.mibAuditInterval": oo.mibAuditInterval, "device-id": oo.deviceID})
+ go func() {
+ time.Sleep(oo.mibAuditInterval)
+ if err := oo.PMibUploadFsm.PFsm.Event(UlEvAuditMib); err != nil {
+ logger.Debugw(ctx, "MibSyncFsm: Can't go to state auditing", log.Fields{"device-id": oo.deviceID, "err": err})
+ }
+ }()
+ }
+}
+
+func (oo *OnuDeviceEntry) enterExaminingMdsState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start GetMds processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+ oo.requestMdsValue(ctx)
+}
+
+func (oo *OnuDeviceEntry) enterResynchronizingState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibResync processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+ logger.Debug(ctx, "function not implemented yet")
+ // TODOs:
+ // VOL-3805 - Provide exclusive OMCI channel for one FSM
+ // VOL-3785 - New event notifications and corresponding performance counters for openonu-adapter-go
+ // VOL-3792 - Support periodical audit via mib resync
+ // VOL-3793 - ONU-reconcile handling after adapter restart based on mib resync
+}
+
+func (oo *OnuDeviceEntry) enterExaminingMdsSuccessState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM",
+ log.Fields{"Start processing on examining MDS success in State": e.FSM.Current(), "device-id": oo.deviceID})
+
+ if oo.getMibFromTemplate(ctx) {
+ oo.baseDeviceHandler.StartReconciling(ctx, true)
+ oo.baseDeviceHandler.AddAllUniPorts(ctx)
+ oo.baseDeviceHandler.SetDeviceReason(cmn.DrInitialMibDownloaded)
+ oo.baseDeviceHandler.SetReadyForOmciConfig(true)
+
+ if !oo.baseDeviceHandler.GetCollectorIsRunning() {
+ // Start PM collector routine
+ go oo.baseDeviceHandler.StartCollector(ctx)
+ }
+ if !oo.baseDeviceHandler.GetAlarmManagerIsRunning(ctx) {
+ go oo.baseDeviceHandler.StartAlarmManager(ctx)
+ }
+ // no need to reconcile additional data for MibDownloadFsm, LockStateFsm, or UnlockStateFsm
+ oo.baseDeviceHandler.ReconcileDeviceTechProf(ctx)
+
+ // start go routine with select() on reconciling flow channel before
+ // starting flow reconciling process to prevent loss of any signal
+ go func() {
+ // In multi-ONU/multi-flow environment stopping reconcilement has to be delayed until
+ // we get a signal that the processing of the last step to rebuild the adapter internal
+ // flow data is finished.
+ select {
+ case success := <-oo.chReconcilingFlowsFinished:
+ if success {
+ logger.Debugw(ctx, "reconciling flows has been finished in time",
+ log.Fields{"device-id": oo.deviceID})
+ oo.baseDeviceHandler.StopReconciling(ctx, true)
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+
+ } else {
+ logger.Debugw(ctx, "wait for reconciling flows aborted",
+ log.Fields{"device-id": oo.deviceID})
+ oo.SetReconcilingFlows(false)
+ }
+ case <-time.After(500 * time.Millisecond):
+ logger.Errorw(ctx, "timeout waiting for reconciling flows to be finished!",
+ log.Fields{"device-id": oo.deviceID})
+ oo.SetReconcilingFlows(false)
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+ }
+ }()
+ oo.baseDeviceHandler.ReconcileDeviceFlowConfig(ctx)
+
+ oo.MutexPersOnuConfig.RLock()
+ if oo.SOnuPersistentData.PersUniDisableDone {
+ oo.MutexPersOnuConfig.RUnlock()
+ oo.baseDeviceHandler.DisableUniPortStateUpdate(ctx)
+ oo.baseDeviceHandler.SetDeviceReason(cmn.DrOmciAdminLock)
+ } else {
+ oo.MutexPersOnuConfig.RUnlock()
+ oo.baseDeviceHandler.EnableUniPortStateUpdate(ctx)
+ }
+ } else {
+ logger.Debugw(ctx, "MibSync FSM",
+ log.Fields{"Getting MIB from template not successful": e.FSM.Current(), "device-id": oo.deviceID})
+ go func() {
+ //switch to reconciling with OMCI config
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+ }()
+ }
+}
+
+func (oo *OnuDeviceEntry) enterAuditingState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibAudit processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+ if oo.baseDeviceHandler.CheckAuditStartCondition(ctx, cmn.CUploadFsm) {
+ oo.requestMdsValue(ctx)
+ } else {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Configuration is ongoing or missing - skip auditing!": e.FSM.Current(), "device-id": oo.deviceID})
+ go func() {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ }()
+ }
+}
+
+func (oo *OnuDeviceEntry) enterReAuditingState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start retest MdsValue processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+ if oo.baseDeviceHandler.CheckAuditStartCondition(ctx, cmn.CUploadFsm) {
+ oo.requestMdsValue(ctx)
+ } else {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Configuration is ongoing or missing - skip re-auditing!": e.FSM.Current(), "device-id": oo.deviceID})
+ go func() {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ }()
+ }
+}
+
+func (oo *OnuDeviceEntry) enterOutOfSyncState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibReconcile processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+ logger.Debug(ctx, "function not implemented yet")
+}
+
+func (oo *OnuDeviceEntry) processMibSyncMessages(ctx context.Context) {
+ logger.Debugw(ctx, "MibSync Msg", log.Fields{"Start routine to process OMCI-messages for device-id": oo.deviceID})
+loop:
+ for {
+ // case <-ctx.Done():
+ // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": onuDeviceEntry.deviceID})
+ // break loop
+ message, ok := <-oo.PMibUploadFsm.CommChan
+ if !ok {
+ logger.Info(ctx, "MibSync Msg", log.Fields{"Message couldn't be read from channel for device-id": oo.deviceID})
+ break loop
+ }
+ logger.Debugw(ctx, "MibSync Msg", log.Fields{"Received message on ONU MibSyncChan for device-id": oo.deviceID})
+
+ switch message.Type {
+ case cmn.TestMsg:
+ msg, _ := message.Data.(cmn.TestMessage)
+ oo.handleTestMsg(ctx, msg)
+ case cmn.OMCI:
+ msg, _ := message.Data.(cmn.OmciMessage)
+ oo.handleOmciMessage(ctx, msg)
+ default:
+ logger.Warn(ctx, "MibSync Msg", log.Fields{"Unknown message type received for device-id": oo.deviceID, "message.Type": message.Type})
+ }
+ }
+ logger.Info(ctx, "MibSync Msg", log.Fields{"Stopped handling of MibSyncChan for device-id": oo.deviceID})
+ // TODO: only this action?
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+}
+
+func (oo *OnuDeviceEntry) handleTestMsg(ctx context.Context, msg cmn.TestMessage) {
+
+ logger.Debugw(ctx, "MibSync Msg", log.Fields{"TestMessage received for device-id": oo.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
+
+ switch msg.TestMessageVal {
+ case cmn.LoadMibTemplateFailed:
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvUploadMib)
+ logger.Debugw(ctx, "MibSync Msg", log.Fields{"state": string(oo.PMibUploadFsm.PFsm.Current())})
+ case cmn.LoadMibTemplateOk:
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ logger.Debugw(ctx, "MibSync Msg", log.Fields{"state": string(oo.PMibUploadFsm.PFsm.Current())})
+ default:
+ logger.Warn(ctx, "MibSync Msg", log.Fields{"Unknown message type received for device-id": oo.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
+ }
+}
+
+func (oo *OnuDeviceEntry) handleOmciMibResetResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+ if oo.PMibUploadFsm.PFsm.Is(UlStResettingMib) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibResetResponse)
+ if msgLayer != nil {
+ msgObj, msgOk := msgLayer.(*omci.MibResetResponse)
+ if msgOk {
+ logger.Debugw(ctx, "MibResetResponse Data", log.Fields{"data-fields": msgObj})
+ if msgObj.Result == me.Success {
+ oo.MutexPersOnuConfig.Lock()
+ oo.SOnuPersistentData.PersMibDataSyncAdpt = 0
+ oo.MutexPersOnuConfig.Unlock()
+ // trigger retrieval of VendorId and SerialNumber
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvGetVendorAndSerial)
+ return
+ }
+ logger.Errorw(ctx, "Omci MibResetResponse Error", log.Fields{"device-id": oo.deviceID, "Error": msgObj.Result})
+ } else {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned", log.Fields{"device-id": oo.deviceID})
+ }
+ } else {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected", log.Fields{"device-id": oo.deviceID})
+ }
+ } else {
+ //in case the last request was MdsGetRequest this issue may appear if the ONU was online before and has received the MIB reset
+ // with Sequence number 0x8000 as last request before - so it may still respond to that
+ // then we may force the ONU to react on the MdsGetRequest with a new message that uses an increased Sequence number
+ oo.mutexLastTxParamStruct.Lock()
+ if oo.lastTxParamStruct.lastTxMessageType == omci.GetRequestType && oo.lastTxParamStruct.repeatCount == 0 {
+ logger.Debugw(ctx, "MibSync FSM - repeat MdsGetRequest (updated SequenceNumber)", log.Fields{"device-id": oo.deviceID})
+ requestedAttributes := me.AttributeValueMap{"MibDataSync": ""}
+ _, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
+ me.OnuDataClassID, cmn.OnuDataMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.PMibUploadFsm.CommChan)
+ if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
+ logger.Errorw(ctx, "ONUData get failed, aborting MibSync", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ return
+ }
+ //TODO: needs extra handling of timeouts
+ oo.lastTxParamStruct.repeatCount = 1
+ oo.mutexLastTxParamStruct.Unlock()
+ return
+ }
+ oo.mutexLastTxParamStruct.Unlock()
+ logger.Errorw(ctx, "unexpected MibResetResponse - ignoring", log.Fields{"device-id": oo.deviceID})
+ //perhaps some still lingering message from some prior activity, let's wait for the real response
+ return
+ }
+ logger.Info(ctx, "MibSync Msg", log.Fields{"Stopped handling of MibSyncChan for device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+}
+
+func (oo *OnuDeviceEntry) handleOmciMibUploadResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibUploadResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected", log.Fields{"device-id": oo.deviceID})
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.MibUploadResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned", log.Fields{"device-id": oo.deviceID})
+ return
+ }
+ logger.Debugw(ctx, "MibUploadResponse Data for:", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
+ /* to be verified / reworked !!! */
+ oo.PDevOmciCC.UploadNoOfCmds = msgObj.NumberOfCommands
+ if oo.PDevOmciCC.UploadSequNo < oo.PDevOmciCC.UploadNoOfCmds {
+ _ = oo.PDevOmciCC.SendMibUploadNext(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), true)
+ //even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
+ // that the lastTxMessageType is correctly set to avoid misinterpreting other responses
+ oo.mutexLastTxParamStruct.Lock()
+ oo.lastTxParamStruct.lastTxMessageType = omci.MibUploadNextRequestType
+ oo.mutexLastTxParamStruct.Unlock()
+ } else {
+ logger.Errorw(ctx, "Invalid number of commands received for:", log.Fields{"device-id": oo.deviceID, "UploadNoOfCmds": oo.PDevOmciCC.UploadNoOfCmds})
+ //TODO right action?
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvTimeout)
+ }
+}
+
+func (oo *OnuDeviceEntry) handleOmciMibUploadNextResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibUploadNextResponse)
+
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected", log.Fields{"device-id": oo.deviceID})
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.MibUploadNextResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned", log.Fields{"device-id": oo.deviceID})
+ 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()
+ oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, meAttributes)
+ }
+ if oo.PDevOmciCC.UploadSequNo < oo.PDevOmciCC.UploadNoOfCmds {
+ _ = oo.PDevOmciCC.SendMibUploadNext(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), true)
+ //even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
+ // that the lastTxMessageType is correctly set to avoid misinterpreting other responses
+ oo.mutexLastTxParamStruct.Lock()
+ oo.lastTxParamStruct.lastTxMessageType = omci.MibUploadNextRequestType
+ oo.mutexLastTxParamStruct.Unlock()
+ } else {
+ oo.pOnuDB.LogMeDb(ctx)
+ err := oo.createAndPersistMibTemplate(ctx)
+ if err != nil {
+ logger.Errorw(ctx, "MibSync - MibTemplate - Failed to create and persist the mib template", log.Fields{"error": err, "device-id": oo.deviceID})
+ }
+
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ }
+}
+
+func (oo *OnuDeviceEntry) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
+ var err error = nil
+
+ oo.mutexLastTxParamStruct.RLock()
+ if oo.lastTxParamStruct.lastTxMessageType != omci.GetRequestType ||
+ oo.lastTxParamStruct.pLastTxMeInstance == nil {
+ //in case the last request was MibReset this issue may appear if the ONU was online before and has received the MDS GetRequest
+ // with Sequence number 0x8000 as last request before - so it may still respond to that
+ // then we may force the ONU to react on the MIB reset with a new message that uses an increased Sequence number
+ if oo.lastTxParamStruct.lastTxMessageType == omci.MibResetRequestType && oo.lastTxParamStruct.repeatCount == 0 {
+ logger.Debugw(ctx, "MibSync FSM - repeat mibReset (updated SequenceNumber)", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PDevOmciCC.SendMibReset(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), true)
+ //TODO: needs extra handling of timeouts
+ oo.lastTxParamStruct.repeatCount = 1
+ oo.mutexLastTxParamStruct.RUnlock()
+ return nil
+ }
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnw(ctx, "unexpected GetResponse - ignoring", log.Fields{"device-id": oo.deviceID})
+ //perhaps some still lingering message from some prior activity, let's wait for the real response
+ return nil
+ }
+ oo.mutexLastTxParamStruct.RUnlock()
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling of MibSyncChan stopped", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling of MibSyncChan stopped: %s", oo.deviceID)
+ }
+ msgObj, msgOk := msgLayer.(*omci.GetResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling of MibSyncChan stopped", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling of MibSyncChan stopped: %s", oo.deviceID)
+ }
+ logger.Debugw(ctx, "MibSync FSM - GetResponse Data", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
+ if msgObj.Result == me.Success {
+ oo.mutexLastTxParamStruct.RLock()
+ entityID := oo.lastTxParamStruct.pLastTxMeInstance.GetEntityID()
+ if msgObj.EntityClass == oo.lastTxParamStruct.pLastTxMeInstance.GetClassID() && msgObj.EntityInstance == entityID {
+ meAttributes := msgObj.Attributes
+ meInstance := oo.lastTxParamStruct.pLastTxMeInstance.GetName()
+ logger.Debugf(ctx, "MibSync FSM - GetResponse Data for %s", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, meInstance)
+ switch meInstance {
+ case "OnuG":
+ oo.mutexLastTxParamStruct.RUnlock()
+ oo.MutexPersOnuConfig.Lock()
+ oo.SOnuPersistentData.PersVendorID = cmn.TrimStringFromMeOctet(meAttributes["VendorId"])
+ snBytes, _ := me.InterfaceToOctets(meAttributes["SerialNumber"])
+ if cmn.OnugSerialNumberLen == len(snBytes) {
+ snVendorPart := fmt.Sprintf("%s", snBytes[:4])
+ snNumberPart := hex.EncodeToString(snBytes[4:])
+ oo.SOnuPersistentData.PersSerialNumber = snVendorPart + snNumberPart
+ logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu-G - VendorId/SerialNumber", log.Fields{"device-id": oo.deviceID,
+ "onuDeviceEntry.vendorID": oo.SOnuPersistentData.PersVendorID, "onuDeviceEntry.serialNumber": oo.SOnuPersistentData.PersSerialNumber})
+ } else {
+ logger.Infow(ctx, "MibSync FSM - SerialNumber has wrong length - fill serialNumber with zeros", log.Fields{"device-id": oo.deviceID, "length": len(snBytes)})
+ oo.SOnuPersistentData.PersSerialNumber = cEmptySerialNumberString
+ }
+ oo.MutexPersOnuConfig.Unlock()
+ // trigger retrieval of EquipmentId
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvGetEquipmentID)
+ return nil
+ case "Onu2G":
+ oo.mutexLastTxParamStruct.RUnlock()
+ oo.MutexPersOnuConfig.Lock()
+ oo.SOnuPersistentData.PersEquipmentID = cmn.TrimStringFromMeOctet(meAttributes["EquipmentId"])
+ logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu2-G - EquipmentId", log.Fields{"device-id": oo.deviceID,
+ "onuDeviceEntry.equipmentID": oo.SOnuPersistentData.PersEquipmentID})
+ oo.MutexPersOnuConfig.Unlock()
+ // trigger retrieval of 1st SW-image info
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvGetFirstSwVersion)
+ return nil
+ case "SoftwareImage":
+ oo.mutexLastTxParamStruct.RUnlock()
+ if entityID > cmn.SecondSwImageMeID {
+ logger.Errorw(ctx, "mibSync FSM - Failed to GetResponse Data for SoftwareImage with expected EntityId",
+ log.Fields{"device-id": oo.deviceID, "entity-ID": entityID})
+ return fmt.Errorf("mibSync FSM - SwResponse Data with unexpected EntityId: %s %x",
+ oo.deviceID, entityID)
+ }
+ // need to use function for go lint complexity
+ oo.handleSwImageIndications(ctx, entityID, meAttributes)
+ return nil
+ case "IpHostConfigData":
+ oo.mutexLastTxParamStruct.RUnlock()
+ macBytes, _ := me.InterfaceToOctets(meAttributes["MacAddress"])
+ oo.MutexPersOnuConfig.Lock()
+ if cmn.OmciMacAddressLen == len(macBytes) {
+ oo.SOnuPersistentData.PersMacAddress = hex.EncodeToString(macBytes[:])
+ logger.Debugw(ctx, "MibSync FSM - GetResponse Data for IpHostConfigData - MacAddress", log.Fields{"device-id": oo.deviceID,
+ "macAddress": oo.SOnuPersistentData.PersMacAddress})
+ } else {
+ logger.Infow(ctx, "MibSync FSM - MacAddress wrong length - fill macAddress with zeros", log.Fields{"device-id": oo.deviceID, "length": len(macBytes)})
+ oo.SOnuPersistentData.PersMacAddress = cEmptyMacAddrString
+ }
+ oo.MutexPersOnuConfig.Unlock()
+ // trigger retrieval of mib template
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvGetMibTemplate)
+ return nil
+ case "OnuData":
+ oo.mutexLastTxParamStruct.RUnlock()
+ oo.checkMdsValue(ctx, meAttributes["MibDataSync"].(uint8))
+ return nil
+ default:
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": meInstance, "device-id": oo.deviceID})
+
+ }
+ } else {
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnf(ctx, "MibSync FSM - Received GetResponse Data for %s with wrong classID or entityID ",
+ log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, msgObj.EntityClass)
+ }
+ } else {
+ if err = oo.handleOmciGetResponseErrors(ctx, msgObj); err == nil {
+ return nil
+ }
+ }
+ logger.Info(ctx, "MibSync Msg", log.Fields{"Stopped handling of MibSyncChan for device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ return err
+}
+
+func (oo *OnuDeviceEntry) handleSwImageIndications(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap) {
+ imageIsCommitted := meAttributes["IsCommitted"].(uint8)
+ imageIsActive := meAttributes["IsActive"].(uint8)
+ imageVersion := cmn.TrimStringFromMeOctet(meAttributes["Version"])
+ oo.MutexPersOnuConfig.RLock()
+ logger.Infow(ctx, "MibSync FSM - GetResponse Data for SoftwareImage",
+ log.Fields{"device-id": oo.deviceID, "entityID": entityID,
+ "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted, "SNR": oo.SOnuPersistentData.PersSerialNumber})
+ oo.MutexPersOnuConfig.RUnlock()
+ if cmn.FirstSwImageMeID == entityID {
+ //always accept the state of the first image (2nd image info should not yet be available)
+ oo.mutexOnuSwImageIndications.Lock()
+ if imageIsActive == cmn.SwIsActive {
+ oo.onuSwImageIndications.ActiveEntityEntry.EntityID = entityID
+ oo.onuSwImageIndications.ActiveEntityEntry.Valid = true
+ oo.onuSwImageIndications.ActiveEntityEntry.Version = imageVersion
+ oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = imageIsCommitted
+ //as the SW version indication may stem from some ONU Down/up event
+ //the complementary image state is to be invalidated
+ // (state of the second image is always expected afterwards or just invalid)
+ oo.onuSwImageIndications.InActiveEntityEntry.Valid = false
+ } else {
+ oo.onuSwImageIndications.InActiveEntityEntry.EntityID = entityID
+ oo.onuSwImageIndications.InActiveEntityEntry.Valid = true
+ oo.onuSwImageIndications.InActiveEntityEntry.Version = imageVersion
+ oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted = imageIsCommitted
+ //as the SW version indication may stem form some ONU Down/up event
+ //the complementary image state is to be invalidated
+ // (state of the second image is always expected afterwards or just invalid)
+ oo.onuSwImageIndications.ActiveEntityEntry.Valid = false
+ }
+ oo.mutexOnuSwImageIndications.Unlock()
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvGetSecondSwVersion)
+ return
+ } else if cmn.SecondSwImageMeID == entityID {
+ //2nd image info might conflict with first image info, in which case we priorize first image info!
+ oo.mutexOnuSwImageIndications.Lock()
+ if imageIsActive == cmn.SwIsActive { //2nd image reported to be active
+ if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+ //conflict exists - state of first image is left active
+ logger.Warnw(ctx, "mibSync FSM - both ONU images are reported as active - assuming 2nd to be inactive",
+ log.Fields{"device-id": oo.deviceID})
+ oo.onuSwImageIndications.InActiveEntityEntry.EntityID = entityID
+ oo.onuSwImageIndications.InActiveEntityEntry.Valid = true ////to indicate that at least something has been reported
+ oo.onuSwImageIndications.InActiveEntityEntry.Version = imageVersion
+ oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted = imageIsCommitted
+ } else { //first image inactive, this one active
+ oo.onuSwImageIndications.ActiveEntityEntry.EntityID = entityID
+ oo.onuSwImageIndications.ActiveEntityEntry.Valid = true
+ oo.onuSwImageIndications.ActiveEntityEntry.Version = imageVersion
+ oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = imageIsCommitted
+ }
+ } else { //2nd image reported to be inactive
+ if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
+ //conflict exists - both images inactive - regard it as ONU failure and assume first image to be active
+ logger.Warnw(ctx, "mibSync FSM - both ONU images are reported as inactive, defining first to be active",
+ log.Fields{"device-id": oo.deviceID})
+ oo.onuSwImageIndications.ActiveEntityEntry.EntityID = cmn.FirstSwImageMeID
+ oo.onuSwImageIndications.ActiveEntityEntry.Valid = true //to indicate that at least something has been reported
+ //copy active commit/version from the previously stored inactive position
+ oo.onuSwImageIndications.ActiveEntityEntry.Version = oo.onuSwImageIndications.InActiveEntityEntry.Version
+ oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted
+ }
+ //in any case we indicate (and possibly overwrite) the second image indications as inactive
+ oo.onuSwImageIndications.InActiveEntityEntry.EntityID = entityID
+ oo.onuSwImageIndications.InActiveEntityEntry.Valid = true
+ oo.onuSwImageIndications.InActiveEntityEntry.Version = imageVersion
+ oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted = imageIsCommitted
+ }
+ oo.mutexOnuSwImageIndications.Unlock()
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvGetMacAddress)
+ return
+ }
+}
+
+func (oo *OnuDeviceEntry) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
+ logger.Debugw(ctx, "MibSync Msg", log.Fields{"OmciMessage received for device-id": oo.deviceID,
+ "msgType": msg.OmciMsg.MessageType, "msg": msg})
+ //further analysis could be done here based on msg.OmciMsg.Payload, e.g. verification of error code ...
+ switch msg.OmciMsg.MessageType {
+ case omci.MibResetResponseType:
+ oo.handleOmciMibResetResponseMessage(ctx, msg)
+
+ case omci.MibUploadResponseType:
+ oo.handleOmciMibUploadResponseMessage(ctx, msg)
+
+ case omci.MibUploadNextResponseType:
+ oo.handleOmciMibUploadNextResponseMessage(ctx, msg)
+
+ case omci.GetResponseType:
+ //TODO: error handling
+ _ = oo.handleOmciGetResponseMessage(ctx, msg)
+
+ default:
+ logger.Warnw(ctx, "Unknown Message Type", log.Fields{"msgType": msg.OmciMsg.MessageType})
+
+ }
+}
+
+func (oo *OnuDeviceEntry) handleOmciGetResponseErrors(ctx context.Context, msgObj *omci.GetResponse) error {
+ var err error = nil
+ logger.Debugf(ctx, "MibSync FSM - erroneous result in GetResponse Data: %s", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, msgObj.Result)
+ // Up to now the following erroneous results have been seen for different ONU-types to indicate an unsupported ME
+ if msgObj.Result == me.UnknownInstance || msgObj.Result == me.UnknownEntity || msgObj.Result == me.ProcessingError || msgObj.Result == me.NotSupported {
+ oo.mutexLastTxParamStruct.RLock()
+ if oo.lastTxParamStruct.pLastTxMeInstance != nil {
+ entityID := oo.lastTxParamStruct.pLastTxMeInstance.GetEntityID()
+ if msgObj.EntityClass == oo.lastTxParamStruct.pLastTxMeInstance.GetClassID() && msgObj.EntityInstance == entityID {
+ meInstance := oo.lastTxParamStruct.pLastTxMeInstance.GetName()
+ switch meInstance {
+ case "IpHostConfigData":
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Debugw(ctx, "MibSync FSM - erroneous result for IpHostConfigData received - ONU doesn't support ME - fill macAddress with zeros",
+ log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
+ oo.MutexPersOnuConfig.Lock()
+ oo.SOnuPersistentData.PersMacAddress = cEmptyMacAddrString
+ oo.MutexPersOnuConfig.Unlock()
+ // trigger retrieval of mib template
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvGetMibTemplate)
+ return nil
+ default:
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnf(ctx, "MibSync FSM - erroneous result for %s received - no exceptional treatment defined", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, meInstance)
+ err = fmt.Errorf("erroneous result for %s received - no exceptional treatment defined: %s", meInstance, oo.deviceID)
+ }
+ } else {
+ oo.mutexLastTxParamStruct.RUnlock()
+ }
+ } else {
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oo.deviceID})
+ }
+ } else {
+ logger.Errorf(ctx, "MibSync FSM - erroneous result in GetResponse Data: %s", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, msgObj.Result)
+ err = fmt.Errorf("erroneous result in GetResponse Data: %s - %s", msgObj.Result, oo.deviceID)
+ }
+ return err
+}
+
+// IsNewOnu - TODO: add comment
+func (oo *OnuDeviceEntry) IsNewOnu() bool {
+ oo.MutexPersOnuConfig.RLock()
+ defer oo.MutexPersOnuConfig.RUnlock()
+ return oo.SOnuPersistentData.PersMibLastDbSync == 0
+}
+
+func isSupportedClassID(meClassID me.ClassID) bool {
+ for _, v := range supportedClassIds {
+ if v == meClassID {
+ return true
+ }
+ }
+ return false
+}
+
+func (oo *OnuDeviceEntry) mibDbVolatileDict(ctx context.Context) error {
+ logger.Debug(ctx, "MibVolatileDict- running from default Entry code")
+ return errors.New("not_implemented")
+}
+
+// createAndPersistMibTemplate method creates a mib template for the device id when operator enables the ONU device for the first time.
+// We are creating a placeholder for "SerialNumber" for ME Class ID 6 and 256 and "MacAddress" for ME Class ID 134 in the template
+// and then storing the template into etcd "service/voltha/omci_mibs/go_templates/verdor_id/equipment_id/software_version" path.
+func (oo *OnuDeviceEntry) createAndPersistMibTemplate(ctx context.Context) error {
+ logger.Debugw(ctx, "MibSync - MibTemplate - path name", log.Fields{"path": oo.mibTemplatePath,
+ "device-id": oo.deviceID})
+
+ oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+ if mibTemplateIsGenerated, exist := oo.pOpenOnuAc.GetMibTemplatesGenerated(oo.mibTemplatePath); exist {
+ if mibTemplateIsGenerated {
+ logger.Debugw(ctx, "MibSync - MibTemplate - another thread has already started to generate it - skip",
+ log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+ return nil
+ }
+ logger.Debugw(ctx, "MibSync - MibTemplate - previous generation attempt seems to be failed - try again",
+ log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ } else {
+ logger.Debugw(ctx, "MibSync - MibTemplate - first ONU-instance of this kind - start generation",
+ log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ }
+ oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, true)
+ oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+
+ currentTime := time.Now()
+ templateMap := make(map[string]interface{})
+ templateMap["TemplateName"] = oo.mibTemplatePath
+ templateMap["TemplateCreated"] = currentTime.Format("2006-01-02 15:04:05.000000")
+
+ firstLevelMap := oo.pOnuDB.MeDb
+ for firstLevelKey, firstLevelValue := range firstLevelMap {
+ logger.Debugw(ctx, "MibSync - MibTemplate - firstLevelKey", log.Fields{"firstLevelKey": firstLevelKey})
+ classID := strconv.Itoa(int(firstLevelKey))
+
+ secondLevelMap := make(map[string]interface{})
+ for secondLevelKey, secondLevelValue := range firstLevelValue {
+ thirdLevelMap := make(map[string]interface{})
+ entityID := strconv.Itoa(int(secondLevelKey))
+ thirdLevelMap["Attributes"] = secondLevelValue
+ thirdLevelMap["InstanceId"] = entityID
+ secondLevelMap[entityID] = thirdLevelMap
+ if classID == "6" || classID == "256" {
+ forthLevelMap := map[string]interface{}(thirdLevelMap["Attributes"].(me.AttributeValueMap))
+ delete(forthLevelMap, "SerialNumber")
+ forthLevelMap["SerialNumber"] = "%SERIAL_NUMBER%"
+
+ }
+ if classID == "134" {
+ forthLevelMap := map[string]interface{}(thirdLevelMap["Attributes"].(me.AttributeValueMap))
+ delete(forthLevelMap, "MacAddress")
+ forthLevelMap["MacAddress"] = "%MAC_ADDRESS%"
+ }
+ }
+ secondLevelMap["ClassId"] = classID
+ templateMap[classID] = secondLevelMap
+ }
+ 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})
+ oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+ oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, false)
+ oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+ return err
+ }
+ err = oo.mibTemplateKVStore.Put(log.WithSpanFromContext(context.TODO(), ctx), oo.mibTemplatePath, string(mibTemplate))
+ if err != nil {
+ logger.Errorw(ctx, "MibSync - MibTemplate - Failed to store template in etcd", log.Fields{"error": err, "device-id": oo.deviceID})
+ oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+ oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, false)
+ oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+ return err
+ }
+ logger.Debugw(ctx, "MibSync - MibTemplate - Stored the template to etcd", log.Fields{"device-id": oo.deviceID})
+ return nil
+}
+
+func (oo *OnuDeviceEntry) requestMdsValue(ctx context.Context) {
+ logger.Debugw(ctx, "Request MDS value", log.Fields{"device-id": oo.deviceID})
+ requestedAttributes := me.AttributeValueMap{"MibDataSync": ""}
+ meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
+ me.OnuDataClassID, cmn.OnuDataMeID, 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 {
+ logger.Errorw(ctx, "ONUData get failed, aborting MibSync FSM!", log.Fields{"device-id": oo.deviceID})
+ pMibUlFsm := oo.PMibUploadFsm
+ if pMibUlFsm != nil {
+ go func(a_pAFsm *cmn.AdapterFsm) {
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+ }(pMibUlFsm)
+ }
+ return
+ }
+ oo.mutexLastTxParamStruct.Lock()
+ oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
+ oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.lastTxParamStruct.repeatCount = 0
+ oo.mutexLastTxParamStruct.Unlock()
+}
+
+func (oo *OnuDeviceEntry) checkMdsValue(ctx context.Context, mibDataSyncOnu uint8) {
+ oo.MutexPersOnuConfig.RLock()
+ logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu-Data - MibDataSync", log.Fields{"device-id": oo.deviceID,
+ "mibDataSyncOnu": mibDataSyncOnu, "PersMibDataSyncAdpt": oo.SOnuPersistentData.PersMibDataSyncAdpt})
+
+ mdsValuesAreEqual := oo.SOnuPersistentData.PersMibDataSyncAdpt == mibDataSyncOnu
+ oo.MutexPersOnuConfig.RUnlock()
+ if oo.PMibUploadFsm.PFsm.Is(UlStAuditing) {
+ if mdsValuesAreEqual {
+ logger.Debugw(ctx, "MibSync FSM - mib audit - MDS check ok", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ } else {
+ logger.Warnw(ctx, "MibSync FSM - mib audit - MDS check failed for the first time!", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+ }
+ } else if oo.PMibUploadFsm.PFsm.Is(UlStReAuditing) {
+ if mdsValuesAreEqual {
+ logger.Debugw(ctx, "MibSync FSM - mib reaudit - MDS check ok", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ } else {
+ logger.Errorw(ctx, "MibSync FSM - mib audit - MDS check failed for the second time!", log.Fields{"device-id": oo.deviceID})
+ //TODO: send new event notification "MDS counter mismatch" to the core
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+ }
+ } else if oo.PMibUploadFsm.PFsm.Is(UlStExaminingMds) {
+ if mdsValuesAreEqual && mibDataSyncOnu != 0 {
+ logger.Debugw(ctx, "MibSync FSM - MDS examination ok", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+ } else {
+ logger.Debugw(ctx, "MibSync FSM - MDS examination failed - new provisioning", log.Fields{"device-id": oo.deviceID})
+ _ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+ }
+ } else {
+ logger.Warnw(ctx, "wrong state for MDS evaluation!", log.Fields{"state": oo.PMibUploadFsm.PFsm.Current(), "device-id": oo.deviceID})
+ }
+}
+
+//GetActiveImageMeID returns the Omci MeId of the active ONU image together with error code for validity
+func (oo *OnuDeviceEntry) GetActiveImageMeID(ctx context.Context) (uint16, error) {
+ oo.mutexOnuSwImageIndications.RLock()
+ if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+ value := oo.onuSwImageIndications.ActiveEntityEntry.EntityID
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return value, nil
+ }
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return 0xFFFF, fmt.Errorf("no valid active image found: %s", oo.deviceID)
+}
+
+//GetInactiveImageMeID returns the Omci MeId of the inactive ONU image together with error code for validity
+func (oo *OnuDeviceEntry) GetInactiveImageMeID(ctx context.Context) (uint16, error) {
+ oo.mutexOnuSwImageIndications.RLock()
+ if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
+ value := oo.onuSwImageIndications.InActiveEntityEntry.EntityID
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return value, nil
+ }
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return 0xFFFF, fmt.Errorf("no valid inactive image found: %s", oo.deviceID)
+}
+
+//IsImageToBeCommitted returns true if the active image is still uncommitted
+func (oo *OnuDeviceEntry) IsImageToBeCommitted(ctx context.Context, aImageID uint16) bool {
+ oo.mutexOnuSwImageIndications.RLock()
+ if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+ if oo.onuSwImageIndications.ActiveEntityEntry.EntityID == aImageID {
+ if oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted == cmn.SwIsUncommitted {
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return true
+ }
+ }
+ }
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return false //all other case are treated as 'nothing to commit
+}
+func (oo *OnuDeviceEntry) getMibFromTemplate(ctx context.Context) bool {
+
+ oo.mibTemplatePath = oo.buildMibTemplatePath()
+ logger.Debugw(ctx, "MibSync FSM - get Mib from template", log.Fields{"path": fmt.Sprintf("%s/%s", cBasePathMibTemplateKvStore, oo.mibTemplatePath),
+ "device-id": oo.deviceID})
+
+ restoredFromMibTemplate := false
+ Value, err := oo.mibTemplateKVStore.Get(log.WithSpanFromContext(context.TODO(), ctx), oo.mibTemplatePath)
+ if err == nil {
+ if Value != nil {
+ logger.Debugf(ctx, "MibSync FSM - Mib template read: Key: %s, Value: %s %s", Value.Key, Value.Value)
+
+ // swap out tokens with specific data
+ mibTmpString, _ := kvstore.ToString(Value.Value)
+ oo.MutexPersOnuConfig.RLock()
+ mibTmpString2 := strings.Replace(mibTmpString, "%SERIAL_NUMBER%", oo.SOnuPersistentData.PersSerialNumber, -1)
+ mibTmpString = strings.Replace(mibTmpString2, "%MAC_ADDRESS%", oo.SOnuPersistentData.PersMacAddress, -1)
+ oo.MutexPersOnuConfig.RUnlock()
+ mibTmpBytes := []byte(mibTmpString)
+ logger.Debugf(ctx, "MibSync FSM - Mib template tokens swapped out: %s", mibTmpBytes)
+
+ var firstLevelMap map[string]interface{}
+ if err = json.Unmarshal(mibTmpBytes, &firstLevelMap); err != nil {
+ logger.Errorw(ctx, "MibSync FSM - Failed to unmarshal template", log.Fields{"error": err, "device-id": oo.deviceID})
+ } else {
+ for firstLevelKey, firstLevelValue := range firstLevelMap {
+ //logger.Debugw(ctx, "MibSync FSM - firstLevelKey", log.Fields{"firstLevelKey": firstLevelKey})
+ if uint16ValidNumber, err := strconv.ParseUint(firstLevelKey, 10, 16); err == nil {
+ meClassID := me.ClassID(uint16ValidNumber)
+ //logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a number in uint16-range", log.Fields{"uint16ValidNumber": uint16ValidNumber})
+ if isSupportedClassID(meClassID) {
+ //logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a supported classID", log.Fields{"meClassID": meClassID})
+ secondLevelMap := firstLevelValue.(map[string]interface{})
+ for secondLevelKey, secondLevelValue := range secondLevelMap {
+ //logger.Debugw(ctx, "MibSync FSM - secondLevelKey", log.Fields{"secondLevelKey": secondLevelKey})
+ if uint16ValidNumber, err := strconv.ParseUint(secondLevelKey, 10, 16); err == nil {
+ meEntityID := uint16(uint16ValidNumber)
+ //logger.Debugw(ctx, "MibSync FSM - secondLevelKey is a number and a valid EntityId", log.Fields{"meEntityID": meEntityID})
+ thirdLevelMap := secondLevelValue.(map[string]interface{})
+ for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
+ if thirdLevelKey == "Attributes" {
+ //logger.Debugw(ctx, "MibSync FSM - thirdLevelKey refers to attributes", log.Fields{"thirdLevelKey": thirdLevelKey})
+ attributesMap := thirdLevelValue.(map[string]interface{})
+ //logger.Debugw(ctx, "MibSync FSM - attributesMap", log.Fields{"attributesMap": attributesMap})
+ oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, attributesMap)
+ restoredFromMibTemplate = true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ logger.Debugw(ctx, "No MIB template found", log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ }
+ } else {
+ logger.Errorf(ctx, "Get from kvstore operation failed for path",
+ log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ }
+ return restoredFromMibTemplate
+}
+
+//CancelProcessing terminates potentially running reconciling processes and stops the FSM
+func (oo *OnuDeviceEntry) CancelProcessing(ctx context.Context) {
+
+ if oo.IsReconcilingFlows() {
+ oo.chReconcilingFlowsFinished <- false
+ }
+ if oo.baseDeviceHandler.IsReconciling() {
+ oo.baseDeviceHandler.StopReconciling(ctx, false)
+ }
+ //the MibSync FSM might be active all the ONU-active time,
+ // hence it must be stopped unconditionally
+ pMibUlFsm := oo.PMibUploadFsm.PFsm
+ if pMibUlFsm != nil {
+ _ = pMibUlFsm.Event(UlEvStop)
+ }
+}
diff --git a/internal/pkg/mib/onu_device_entry.go b/internal/pkg/mib/onu_device_entry.go
new file mode 100755
index 0000000..ebf8de8
--- /dev/null
+++ b/internal/pkg/mib/onu_device_entry.go
@@ -0,0 +1,992 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/looplab/fsm"
+ "github.com/opencord/omci-lib-go"
+ me "github.com/opencord/omci-lib-go/generated"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db"
+ "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
+ vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
+
+ "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"
+ "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/swupg"
+)
+
+// events of MibUpload FSM
+const (
+ UlEvStart = "UlEvStart"
+ UlEvResetMib = "UlEvResetMib"
+ UlEvGetVendorAndSerial = "UlEvGetVendorAndSerial"
+ UlEvGetEquipmentID = "UlEvGetEquipmentId"
+ UlEvGetFirstSwVersion = "UlEvGetFirstSwVersion"
+ UlEvGetSecondSwVersion = "UlEvGetSecondSwVersion"
+ UlEvGetMacAddress = "UlEvGetMacAddress"
+ UlEvGetMibTemplate = "UlEvGetMibTemplate"
+ UlEvUploadMib = "UlEvUploadMib"
+ UlEvExamineMds = "UlEvExamineMds"
+ UlEvSuccess = "UlEvSuccess"
+ UlEvMismatch = "UlEvMismatch"
+ UlEvAuditMib = "UlEvAuditMib"
+ UlEvForceResync = "UlEvForceResync"
+ UlEvDiffsFound = "UlEvDiffsFound"
+ UlEvTimeout = "UlEvTimeout"
+ UlEvStop = "UlEvStop"
+)
+
+// states of MibUpload FSM
+const (
+ UlStDisabled = "UlStDisabled"
+ UlStStarting = "UlStStarting"
+ UlStResettingMib = "UlStResettingMib"
+ UlStGettingVendorAndSerial = "UlStGettingVendorAndSerial"
+ UlStGettingEquipmentID = "UlStGettingEquipmentID"
+ UlStGettingFirstSwVersion = "UlStGettingFirstSwVersion"
+ UlStGettingSecondSwVersion = "UlStGettingSecondSwVersion"
+ UlStGettingMacAddress = "UlStGettingMacAddress"
+ UlStGettingMibTemplate = "UlStGettingMibTemplate"
+ UlStUploading = "UlStUploading"
+ UlStUploadDone = "UlStUploadDone"
+ UlStInSync = "UlStInSync"
+ UlStExaminingMds = "UlStExaminingMds"
+ UlStResynchronizing = "UlStResynchronizing"
+ UlStExaminingMdsSuccess = "UlStExaminingMdsSuccess"
+ UlStAuditing = "UlStAuditing"
+ UlStReAuditing = "UlStReAuditing"
+ UlStOutOfSync = "UlStOutOfSync"
+)
+
+// CMibUlFsmIdleState - TODO: add comment
+const CMibUlFsmIdleState = UlStInSync
+
+// events of MibDownload FSM
+const (
+ DlEvStart = "DlEvStart"
+ DlEvCreateGal = "DlEvCreateGal"
+ DlEvRxGalResp = "DlEvRxGalResp"
+ DlEvRxOnu2gResp = "DlEvRxOnu2gResp"
+ DlEvRxBridgeResp = "DlEvRxBridgeResp"
+ DlEvTimeoutSimple = "DlEvTimeoutSimple"
+ DlEvTimeoutBridge = "DlEvTimeoutBridge"
+ DlEvReset = "DlEvReset"
+ DlEvRestart = "DlEvRestart"
+)
+
+// states of MibDownload FSM
+const (
+ DlStDisabled = "DlStDisabled"
+ DlStStarting = "DlStStarting"
+ DlStCreatingGal = "DlStCreatingGal"
+ DlStSettingOnu2g = "DlStSettingOnu2g"
+ DlStBridgeInit = "DlStBridgeInit"
+ DlStDownloaded = "DlStDownloaded"
+ DlStResetting = "DlStResetting"
+)
+
+// CMibDlFsmIdleState - TODO: add comment
+const CMibDlFsmIdleState = DlStDisabled
+
+const (
+ // NOTE that this hardcoded to service/voltha as the MIB template is shared across stacks
+ cBasePathMibTemplateKvStore = "service/voltha/omci_mibs/go_templates"
+ cSuffixMibTemplateKvStore = "%s/%s/%s"
+ cBasePathOnuKVStore = "%s/openonu"
+)
+
+const cEmptyMacAddrString = "000000000000"
+const cEmptySerialNumberString = "0000000000000000"
+
+type uniPersConfig struct {
+ PersUniID uint8 `json:"uni_id"`
+ PersTpPathMap map[uint8]string `json:"PersTpPathMap"` // tp-id to tp-path map
+ PersFlowParams []cmn.UniVlanFlowParams `json:"flow_params"` //as defined in omci_ani_config.go
+}
+
+type onuPersistentData struct {
+ PersOnuID uint32 `json:"onu_id"`
+ PersIntfID uint32 `json:"intf_id"`
+ PersSerialNumber string `json:"serial_number"`
+ PersMacAddress string `json:"mac_address"`
+ PersVendorID string `json:"vendor_id"`
+ PersEquipmentID string `json:"equipment_id"`
+ PersActiveSwVersion string `json:"active_sw_version"`
+ PersAdminState string `json:"admin_state"`
+ PersOperState string `json:"oper_state"`
+ PersUniUnlockDone bool `json:"uni_unlock_done"`
+ PersUniDisableDone bool `json:"uni_disable_done"`
+ PersMibAuditInterval time.Duration `json:"mib_audit_interval"`
+ PersMibLastDbSync uint32 `json:"mib_last_db_sync"`
+ PersMibDataSyncAdpt uint8 `json:"mib_data_sync_adpt"`
+ PersUniConfig []uniPersConfig `json:"uni_config"`
+ PersAlarmAuditInterval time.Duration `json:"alarm_audit_interval"`
+ PersTcontMap map[uint16]uint16 `json:"tcont_map"` //alloc-id to me-instance-id map
+}
+
+// OnuDeviceEntry - ONU device info and FSM events.
+type OnuDeviceEntry struct {
+ deviceID string
+ baseDeviceHandler cmn.IdeviceHandler
+ pOpenOnuAc cmn.IopenONUAC
+ pOnuTP cmn.IonuUniTechProf
+ coreClient *vgrpc.Client
+ PDevOmciCC *cmn.OmciCC
+ pOnuDB *devdb.OnuDeviceDB
+ mibTemplateKVStore *db.Backend
+ MutexPersOnuConfig sync.RWMutex
+ SOnuPersistentData onuPersistentData
+ reconcilingFlows bool
+ mutexReconcilingFlowsFlag sync.RWMutex
+ chReconcilingFlowsFinished chan bool //channel to indicate that reconciling of flows has been finished
+ mibTemplatePath string
+ mutexOnuKVStore sync.RWMutex
+ onuKVStore *db.Backend
+ onuKVStorePath string
+ mutexOnuKVStoreProcResult sync.RWMutex
+ onuKVStoreProcResult error //error indication of processing
+ chOnuKvProcessingStep chan uint8
+ mutexOnuSwImageIndications sync.RWMutex
+ onuSwImageIndications cmn.SswImageIndications
+ MutexOnuImageStatus sync.RWMutex
+ POnuImageStatus *swupg.OnuImageStatus
+ //lockDeviceEntries sync.RWMutex
+ mibDbClass func(context.Context) error
+ supportedFsms cmn.OmciDeviceFsms
+ devState cmn.OnuDeviceEvent
+ // Audit and MDS
+ mibAuditInterval time.Duration
+ alarmAuditInterval time.Duration
+ // TODO: periodical mib resync will be implemented with story VOL-3792
+ //mibNextDbResync uint32
+
+ // for mibUpload
+ PMibUploadFsm *cmn.AdapterFsm //could be handled dynamically and more general as pcmn.AdapterFsm - perhaps later
+ mutexLastTxParamStruct sync.RWMutex
+ lastTxParamStruct sLastTxMeParameter
+ // for mibDownload
+ PMibDownloadFsm *cmn.AdapterFsm //could be handled dynamically and more general as pcmn.AdapterFsm - perhaps later
+ //remark: general usage of pAdapterFsm would require generalization of CommChan usage and internal event setting
+ // within the FSM event procedures
+ mutexPLastTxMeInstance sync.RWMutex
+ pLastTxMeInstance *me.ManagedEntity
+ omciMessageReceived chan bool //seperate channel needed by DownloadFsm
+ omciRebootMessageReceivedChannel chan cmn.Message // channel needed by reboot request
+
+ mutexTcontMap sync.RWMutex
+}
+
+//NewOnuDeviceEntry returns a new instance of a OnuDeviceEntry
+//mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
+func NewOnuDeviceEntry(ctx context.Context, cc *vgrpc.Client, dh cmn.IdeviceHandler,
+ openonu cmn.IopenONUAC) *OnuDeviceEntry {
+ var onuDeviceEntry OnuDeviceEntry
+ onuDeviceEntry.deviceID = dh.GetDeviceID()
+ logger.Debugw(ctx, "init-onuDeviceEntry", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.baseDeviceHandler = dh
+ onuDeviceEntry.pOpenOnuAc = openonu
+ onuDeviceEntry.coreClient = cc
+ onuDeviceEntry.devState = cmn.DeviceStatusInit
+ onuDeviceEntry.SOnuPersistentData.PersUniConfig = make([]uniPersConfig, 0)
+ onuDeviceEntry.SOnuPersistentData.PersTcontMap = make(map[uint16]uint16)
+ onuDeviceEntry.chReconcilingFlowsFinished = make(chan bool)
+ onuDeviceEntry.reconcilingFlows = false
+ onuDeviceEntry.chOnuKvProcessingStep = make(chan uint8)
+ onuDeviceEntry.omciRebootMessageReceivedChannel = make(chan cmn.Message, 2048)
+ //openomciagent.lockDeviceHandlersMap = sync.RWMutex{}
+ //OMCI related databases are on a per-agent basis. State machines and tasks
+ //are per ONU Vendor
+ //
+ // MIB Synchronization Database - possible overloading from arguments
+ supportedFsms := onuDeviceEntry.pOpenOnuAc.GetSupportedFsms()
+ if supportedFsms != nil {
+ onuDeviceEntry.supportedFsms = *supportedFsms
+ } else {
+ // This branch is currently not used and is for potential future usage of alternative MIB Sync FSMs only!
+ //var mibSyncFsm = NewMibSynchronizer()
+ // use some internal defaults, if not defined from outside
+ onuDeviceEntry.supportedFsms = cmn.OmciDeviceFsms{
+ "mib-synchronizer": {
+ //mibSyncFsm, // Implements the MIB synchronization state machine
+ DatabaseClass: onuDeviceEntry.mibDbVolatileDict, // Implements volatile ME MIB database
+ //true, // Advertise events on OpenOMCI event bus
+ AuditInterval: dh.GetAlarmAuditInterval(), // Time to wait between MIB audits. 0 to disable audits.
+ // map[string]func() error{
+ // "mib-upload": onuDeviceEntry.MibUploadTask,
+ // "mib-template": onuDeviceEntry.MibTemplateTask,
+ // "get-mds": onuDeviceEntry.GetMdsTask,
+ // "mib-audit": onuDeviceEntry.GetMdsTask,
+ // "mib-resync": onuDeviceEntry.MibResyncTask,
+ // "mib-reconcile": onuDeviceEntry.MibReconcileTask,
+ // },
+ },
+ }
+ }
+ onuDeviceEntry.mibDbClass = onuDeviceEntry.supportedFsms["mib-synchronizer"].DatabaseClass
+ logger.Debug(ctx, "access2mibDbClass")
+ go onuDeviceEntry.mibDbClass(ctx)
+ if !dh.IsReconciling() {
+ onuDeviceEntry.mibAuditInterval = onuDeviceEntry.supportedFsms["mib-synchronizer"].AuditInterval
+ onuDeviceEntry.SOnuPersistentData.PersMibAuditInterval = onuDeviceEntry.mibAuditInterval
+ onuDeviceEntry.alarmAuditInterval = dh.GetAlarmAuditInterval()
+ onuDeviceEntry.SOnuPersistentData.PersAlarmAuditInterval = onuDeviceEntry.alarmAuditInterval
+ } else {
+ logger.Debugw(ctx, "reconciling - take audit interval from persistent data", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ // TODO: This is a preparation for VOL-VOL-3811 to preserve config history in case of
+ // vendor- or deviceID-specific configurations via voltctl-commands
+ onuDeviceEntry.mibAuditInterval = onuDeviceEntry.SOnuPersistentData.PersMibAuditInterval
+ onuDeviceEntry.alarmAuditInterval = onuDeviceEntry.SOnuPersistentData.PersAlarmAuditInterval
+ }
+ logger.Debugw(ctx, "MibAuditInterval and AlarmAuditInterval is set to", log.Fields{"mib-audit-interval": onuDeviceEntry.mibAuditInterval,
+ "alarm-audit-interval": onuDeviceEntry.alarmAuditInterval})
+ // TODO: periodical mib resync will be implemented with story VOL-3792
+ //onuDeviceEntry.mibNextDbResync = 0
+
+ // Omci related Mib upload sync state machine
+ mibUploadChan := make(chan cmn.Message, 2048)
+ onuDeviceEntry.PMibUploadFsm = cmn.NewAdapterFsm("MibUpload", onuDeviceEntry.deviceID, mibUploadChan)
+ onuDeviceEntry.PMibUploadFsm.PFsm = fsm.NewFSM(
+ UlStDisabled,
+ fsm.Events{
+
+ {Name: UlEvStart, Src: []string{UlStDisabled}, Dst: UlStStarting},
+
+ {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: UlEvGetSecondSwVersion, Src: []string{UlStGettingFirstSwVersion}, Dst: UlStGettingSecondSwVersion},
+ {Name: UlEvGetMacAddress, Src: []string{UlStGettingSecondSwVersion}, Dst: UlStGettingMacAddress},
+ {Name: UlEvGetMibTemplate, Src: []string{UlStGettingMacAddress}, Dst: UlStGettingMibTemplate},
+
+ {Name: UlEvUploadMib, Src: []string{UlStGettingMibTemplate}, Dst: UlStUploading},
+ {Name: UlEvExamineMds, Src: []string{UlStStarting}, Dst: UlStExaminingMds},
+
+ {Name: UlEvSuccess, Src: []string{UlStGettingMibTemplate}, Dst: UlStUploadDone},
+ {Name: UlEvSuccess, Src: []string{UlStUploading}, Dst: UlStUploadDone},
+
+ {Name: UlEvSuccess, Src: []string{UlStUploadDone}, Dst: UlStInSync},
+ //{Name: UlEvSuccess, Src: []string{UlStExaminingMds}, Dst: UlStInSync},
+ {Name: UlEvSuccess, Src: []string{UlStExaminingMds}, Dst: UlStExaminingMdsSuccess},
+ // TODO: As long as mib-resynchronizing is not implemented, failed MDS-examination triggers
+ // mib-reset and new provisioning at this point
+ //{Name: UlEvMismatch, Src: []string{UlStExaminingMds}, Dst: UlStResynchronizing},
+ {Name: UlEvMismatch, Src: []string{UlStExaminingMds}, Dst: UlStResettingMib},
+
+ {Name: UlEvSuccess, Src: []string{UlStExaminingMdsSuccess}, Dst: UlStInSync},
+ {Name: UlEvMismatch, Src: []string{UlStExaminingMdsSuccess}, Dst: UlStResettingMib},
+
+ {Name: UlEvAuditMib, Src: []string{UlStInSync}, Dst: UlStAuditing},
+
+ {Name: UlEvSuccess, Src: []string{UlStOutOfSync}, Dst: UlStInSync},
+ {Name: UlEvAuditMib, Src: []string{UlStOutOfSync}, Dst: UlStAuditing},
+
+ {Name: UlEvSuccess, Src: []string{UlStAuditing}, Dst: UlStInSync},
+ {Name: UlEvMismatch, Src: []string{UlStAuditing}, Dst: UlStReAuditing},
+ {Name: UlEvForceResync, Src: []string{UlStAuditing}, Dst: UlStResynchronizing},
+
+ {Name: UlEvSuccess, Src: []string{UlStReAuditing}, Dst: UlStInSync},
+ {Name: UlEvMismatch, Src: []string{UlStReAuditing}, Dst: UlStResettingMib},
+
+ {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, UlStExaminingMds,
+ UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStStarting},
+
+ {Name: UlEvStop, Src: []string{UlStStarting, UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipmentID, UlStGettingFirstSwVersion,
+ UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing, UlStExaminingMds,
+ UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStDisabled},
+ },
+
+ fsm.Callbacks{
+ "enter_state": func(e *fsm.Event) { onuDeviceEntry.PMibUploadFsm.LogFsmStateChange(ctx, e) },
+ "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_" + 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) },
+ "enter_" + UlStGettingMibTemplate: func(e *fsm.Event) { onuDeviceEntry.enterGettingMibTemplateState(ctx, e) },
+ "enter_" + UlStUploading: func(e *fsm.Event) { onuDeviceEntry.enterUploadingState(ctx, e) },
+ "enter_" + UlStUploadDone: func(e *fsm.Event) { onuDeviceEntry.enterUploadDoneState(ctx, e) },
+ "enter_" + UlStExaminingMds: func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsState(ctx, e) },
+ "enter_" + UlStResynchronizing: func(e *fsm.Event) { onuDeviceEntry.enterResynchronizingState(ctx, e) },
+ "enter_" + UlStExaminingMdsSuccess: func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsSuccessState(ctx, e) },
+ "enter_" + UlStAuditing: func(e *fsm.Event) { onuDeviceEntry.enterAuditingState(ctx, e) },
+ "enter_" + UlStReAuditing: func(e *fsm.Event) { onuDeviceEntry.enterReAuditingState(ctx, e) },
+ "enter_" + UlStOutOfSync: func(e *fsm.Event) { onuDeviceEntry.enterOutOfSyncState(ctx, e) },
+ "enter_" + UlStInSync: func(e *fsm.Event) { onuDeviceEntry.enterInSyncState(ctx, e) },
+ },
+ )
+ // Omci related Mib download state machine
+ mibDownloadChan := make(chan cmn.Message, 2048)
+ onuDeviceEntry.PMibDownloadFsm = cmn.NewAdapterFsm("MibDownload", onuDeviceEntry.deviceID, mibDownloadChan)
+ onuDeviceEntry.PMibDownloadFsm.PFsm = fsm.NewFSM(
+ DlStDisabled,
+ fsm.Events{
+
+ {Name: DlEvStart, Src: []string{DlStDisabled}, Dst: DlStStarting},
+
+ {Name: DlEvCreateGal, Src: []string{DlStStarting}, Dst: DlStCreatingGal},
+ {Name: DlEvRxGalResp, Src: []string{DlStCreatingGal}, Dst: DlStSettingOnu2g},
+ {Name: DlEvRxOnu2gResp, Src: []string{DlStSettingOnu2g}, Dst: DlStBridgeInit},
+ // the bridge state is used for multi ME config for alle UNI related ports
+ // maybe such could be reflected in the state machine as well (port number parametrized)
+ // but that looks not straightforward here - so we keep it simple here for the beginning(?)
+ {Name: DlEvRxBridgeResp, Src: []string{DlStBridgeInit}, Dst: DlStDownloaded},
+
+ {Name: DlEvTimeoutSimple, Src: []string{DlStCreatingGal, DlStSettingOnu2g}, Dst: DlStStarting},
+ {Name: DlEvTimeoutBridge, Src: []string{DlStBridgeInit}, Dst: DlStStarting},
+
+ {Name: DlEvReset, Src: []string{DlStStarting, DlStCreatingGal, DlStSettingOnu2g,
+ DlStBridgeInit, DlStDownloaded}, Dst: DlStResetting},
+ // exceptional treatment for all states except DlStResetting
+ {Name: DlEvRestart, Src: []string{DlStStarting, DlStCreatingGal, DlStSettingOnu2g,
+ DlStBridgeInit, DlStDownloaded, DlStResetting}, Dst: DlStDisabled},
+ },
+
+ fsm.Callbacks{
+ "enter_state": func(e *fsm.Event) { onuDeviceEntry.PMibDownloadFsm.LogFsmStateChange(ctx, e) },
+ "enter_" + DlStStarting: func(e *fsm.Event) { onuDeviceEntry.enterDLStartingState(ctx, e) },
+ "enter_" + DlStCreatingGal: func(e *fsm.Event) { onuDeviceEntry.enterCreatingGalState(ctx, e) },
+ "enter_" + DlStSettingOnu2g: func(e *fsm.Event) { onuDeviceEntry.enterSettingOnu2gState(ctx, e) },
+ "enter_" + DlStBridgeInit: func(e *fsm.Event) { onuDeviceEntry.enterBridgeInitState(ctx, e) },
+ "enter_" + DlStDownloaded: func(e *fsm.Event) { onuDeviceEntry.enterDownloadedState(ctx, e) },
+ "enter_" + DlStResetting: func(e *fsm.Event) { onuDeviceEntry.enterResettingState(ctx, e) },
+ },
+ )
+ if onuDeviceEntry.PMibDownloadFsm == nil || onuDeviceEntry.PMibDownloadFsm.PFsm == nil {
+ logger.Errorw(ctx, "MibDownloadFsm could not be instantiated", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ // TODO some specific error treatment - or waiting for crash ?
+ }
+
+ onuDeviceEntry.mibTemplateKVStore = onuDeviceEntry.baseDeviceHandler.SetBackend(ctx, cBasePathMibTemplateKvStore)
+ if onuDeviceEntry.mibTemplateKVStore == nil {
+ logger.Errorw(ctx, "Can't access mibTemplateKVStore - no backend connection to service",
+ log.Fields{"device-id": onuDeviceEntry.deviceID, "service": cBasePathMibTemplateKvStore})
+ }
+
+ onuDeviceEntry.onuKVStorePath = onuDeviceEntry.deviceID
+ baseKvStorePath := fmt.Sprintf(cBasePathOnuKVStore, dh.GetBackendPathPrefix())
+ onuDeviceEntry.onuKVStore = onuDeviceEntry.baseDeviceHandler.SetBackend(ctx, baseKvStorePath)
+ if onuDeviceEntry.onuKVStore == nil {
+ logger.Errorw(ctx, "Can't access onuKVStore - no backend connection to service",
+ log.Fields{"device-id": onuDeviceEntry.deviceID, "service": baseKvStorePath})
+ }
+
+ // Alarm Synchronization Database
+
+ //self._alarm_db = None
+ //self._alarm_database_cls = support_classes['alarm-synchronizer']['database']
+ return &onuDeviceEntry
+}
+
+//Start starts (logs) the omci agent
+func (oo *OnuDeviceEntry) Start(ctx context.Context) error {
+ logger.Debugw(ctx, "OnuDeviceEntry-starting", log.Fields{"for device-id": oo.deviceID})
+ if oo.PDevOmciCC == nil {
+ oo.PDevOmciCC = cmn.NewOmciCC(ctx, oo.deviceID, oo.baseDeviceHandler, oo, oo.baseDeviceHandler.GetOnuAlarmManager(), oo.coreClient)
+ if oo.PDevOmciCC == nil {
+ logger.Errorw(ctx, "Could not create devOmciCc - abort", log.Fields{"for device-id": oo.deviceID})
+ return fmt.Errorf("could not create devOmciCc %s", oo.deviceID)
+ }
+ }
+ return nil
+}
+
+//Stop stops/resets the omciCC
+func (oo *OnuDeviceEntry) Stop(ctx context.Context, abResetOmciCC bool) error {
+ logger.Debugw(ctx, "OnuDeviceEntry-stopping", log.Fields{"for device-id": oo.deviceID})
+ if abResetOmciCC && (oo.PDevOmciCC != nil) {
+ _ = oo.PDevOmciCC.Stop(ctx)
+ }
+ //to allow for all event notifications again when re-using the device and omciCC
+ oo.devState = cmn.DeviceStatusInit
+ return nil
+}
+
+// Reboot - TODO: add comment
+func (oo *OnuDeviceEntry) Reboot(ctx context.Context) error {
+ logger.Debugw(ctx, "OnuDeviceEntry-rebooting", log.Fields{"for device-id": oo.deviceID})
+ if oo.PDevOmciCC != nil {
+ if err := oo.PDevOmciCC.SendReboot(ctx, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.omciRebootMessageReceivedChannel); err != nil {
+ logger.Errorw(ctx, "onu didn't reboot", log.Fields{"for device-id": oo.deviceID})
+ return err
+ }
+ }
+ return nil
+}
+
+// WaitForRebootResponse - TODO: add comment
+func (oo *OnuDeviceEntry) WaitForRebootResponse(ctx context.Context, responseChannel chan cmn.Message) error {
+ select {
+ case <-time.After(oo.PDevOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
+ logger.Warnw(ctx, "reboot timeout", log.Fields{"for device-id": oo.deviceID})
+ return fmt.Errorf("rebootTimeout")
+ case data := <-responseChannel:
+ switch data.Data.(cmn.OmciMessage).OmciMsg.MessageType {
+ case omci.RebootResponseType:
+ {
+ msgLayer := (*data.Data.(cmn.OmciMessage).OmciPacket).Layer(omci.LayerTypeRebootResponse)
+ if msgLayer == nil {
+ return fmt.Errorf("omci Msg layer could not be detected for RebootResponseType")
+ }
+ msgObj, msgOk := msgLayer.(*omci.RebootResponse)
+ if !msgOk {
+ return fmt.Errorf("omci Msg layer could not be assigned for RebootResponseType %s", oo.deviceID)
+ }
+ logger.Debugw(ctx, "RebootResponse data", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success {
+ logger.Errorw(ctx, "Omci RebootResponse result error", log.Fields{"device-id": oo.deviceID, "Error": msgObj.Result})
+ // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ return fmt.Errorf("omci RebootResponse result error indication %s for device %s",
+ msgObj.Result, oo.deviceID)
+ }
+ return nil
+ }
+ }
+ logger.Warnw(ctx, "Reboot response message type error", log.Fields{"for device-id": oo.deviceID})
+ return fmt.Errorf("unexpected OmciResponse type received %s", oo.deviceID)
+ }
+}
+
+//Relay the InSync message via Handler to Rw core - Status update
+func (oo *OnuDeviceEntry) transferSystemEvent(ctx context.Context, devEvent cmn.OnuDeviceEvent) {
+ logger.Debugw(ctx, "relaying system-event", log.Fields{"Event": devEvent})
+ // decouple the handler transfer from further processing here
+ // TODO!!! check if really no synch is required within the system e.g. to ensure following steps ..
+ if devEvent == cmn.MibDatabaseSync {
+ if oo.devState < cmn.MibDatabaseSync { //devState has not been synced yet
+ oo.devState = cmn.MibDatabaseSync
+ go oo.baseDeviceHandler.DeviceProcStatusUpdate(ctx, devEvent)
+ //TODO!!! device control: next step: start MIB capability verification from here ?!!!
+ } else {
+ logger.Debugw(ctx, "mibinsync-event in some already synced state - ignored", log.Fields{"state": oo.devState})
+ }
+ } else if devEvent == cmn.MibDownloadDone {
+ if oo.devState < cmn.MibDownloadDone { //devState has not been synced yet
+ oo.devState = cmn.MibDownloadDone
+ go oo.baseDeviceHandler.DeviceProcStatusUpdate(ctx, devEvent)
+ } else {
+ logger.Debugw(ctx, "mibdownloaddone-event was already seen - ignored", log.Fields{"state": oo.devState})
+ }
+ } else {
+ logger.Warnw(ctx, "device-event not yet handled", log.Fields{"state": devEvent})
+ }
+}
+
+// RestoreDataFromOnuKvStore - TODO: add comment
+func (oo *OnuDeviceEntry) RestoreDataFromOnuKvStore(ctx context.Context) error {
+ if oo.onuKVStore == nil {
+ logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
+ return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", oo.deviceID))
+ }
+ 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)}
+ oo.mutexOnuKVStore.RLock()
+ Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
+ oo.mutexOnuKVStore.RUnlock()
+ if err == nil {
+ if Value != nil {
+ logger.Debugw(ctx, "ONU-data read",
+ log.Fields{"Key": Value.Key, "device-id": oo.deviceID})
+ tmpBytes, _ := kvstore.ToByte(Value.Value)
+
+ if err = json.Unmarshal(tmpBytes, &oo.SOnuPersistentData); err != nil {
+ logger.Errorw(ctx, "unable to unmarshal ONU-data", log.Fields{"error": err, "device-id": oo.deviceID})
+ return fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-ONU-data-%s", oo.deviceID))
+ }
+ logger.Debugw(ctx, "ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
+ "device-id": oo.deviceID})
+ } else {
+ logger.Debugw(ctx, "no ONU-data found", log.Fields{"path": oo.onuKVStorePath, "device-id": oo.deviceID})
+ return fmt.Errorf("no-ONU-data-found")
+ }
+ } else {
+ logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": oo.deviceID})
+ return fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s", oo.deviceID))
+ }
+ return nil
+}
+
+// DeleteDataFromOnuKvStore - TODO: add comment
+func (oo *OnuDeviceEntry) DeleteDataFromOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ if oo.onuKVStore == nil {
+ logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
+ oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: onuKVStore not set"))
+ return
+ }
+ var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
+ go oo.deletePersistentData(ctx, processingStep)
+ if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
+ //timeout or error detected
+ logger.Debugw(ctx, "ONU-data not deleted - abort", log.Fields{"device-id": oo.deviceID})
+ oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: during kv-access"))
+ return
+ }
+}
+
+func (oo *OnuDeviceEntry) deletePersistentData(ctx context.Context, aProcessingStep uint8) {
+
+ logger.Debugw(ctx, "delete and clear internal persistency data", log.Fields{"device-id": oo.deviceID})
+
+ oo.MutexPersOnuConfig.Lock()
+ defer oo.MutexPersOnuConfig.Unlock()
+
+ 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)}
+ logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
+ oo.mutexOnuKVStore.Lock()
+ err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)
+ oo.mutexOnuKVStore.Unlock()
+ if err != nil {
+ logger.Errorw(ctx, "unable to delete in KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
+ oo.chOnuKvProcessingStep <- 0 //error indication
+ return
+ }
+ oo.chOnuKvProcessingStep <- aProcessingStep //done
+}
+
+// UpdateOnuKvStore - TODO: add comment
+func (oo *OnuDeviceEntry) UpdateOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ if oo.onuKVStore == nil {
+ logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
+ oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: onuKVStore not set"))
+ return
+ }
+ var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
+ go oo.storeDataInOnuKvStore(ctx, processingStep)
+ if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
+ //timeout or error detected
+ logger.Debugw(ctx, "ONU-data not written - abort", log.Fields{"device-id": oo.deviceID})
+ oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: during writing process"))
+ return
+ }
+}
+
+func (oo *OnuDeviceEntry) storeDataInOnuKvStore(ctx context.Context, aProcessingStep uint8) {
+
+ oo.MutexPersOnuConfig.Lock()
+ defer oo.MutexPersOnuConfig.Unlock()
+ //assign values which are not already present when NewOnuDeviceEntry() is called
+ onuIndication := oo.baseDeviceHandler.GetOnuIndication()
+ oo.SOnuPersistentData.PersOnuID = onuIndication.OnuId
+ oo.SOnuPersistentData.PersIntfID = onuIndication.IntfId
+ //TODO: verify usage of these values during restart UC
+ oo.SOnuPersistentData.PersAdminState = onuIndication.AdminState
+ oo.SOnuPersistentData.PersOperState = onuIndication.OperState
+
+ logger.Debugw(ctx, "Update ONU-data in KVStore", log.Fields{"device-id": oo.deviceID, "SOnuPersistentData": oo.SOnuPersistentData})
+
+ Value, err := json.Marshal(oo.SOnuPersistentData)
+ if err != nil {
+ logger.Errorw(ctx, "unable to marshal ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
+ "device-id": oo.deviceID, "err": err})
+ oo.chOnuKvProcessingStep <- 0 //error indication
+ return
+ }
+ oo.pOpenOnuAc.RLockMutexDeviceHandlersMap()
+ if _, exist := oo.pOpenOnuAc.GetDeviceHandler(oo.deviceID); !exist {
+ logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
+ oo.chOnuKvProcessingStep <- aProcessingStep
+ oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
+ return
+ }
+ oo.baseDeviceHandler.RLockMutexDeletionInProgressFlag()
+ if oo.baseDeviceHandler.GetDeletionInProgress() {
+ logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
+ oo.chOnuKvProcessingStep <- aProcessingStep
+ oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
+ oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
+ return
+ }
+ oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
+ oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
+
+ oo.mutexOnuKVStore.Lock()
+ err = oo.onuKVStore.Put(ctx, oo.onuKVStorePath, Value)
+ oo.mutexOnuKVStore.Unlock()
+ if err != nil {
+ logger.Errorw(ctx, "unable to write ONU-data into KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
+ oo.chOnuKvProcessingStep <- 0 //error indication
+ return
+ }
+ oo.chOnuKvProcessingStep <- aProcessingStep //done
+}
+
+// UpdateOnuUniTpPath - TODO: add comment
+func (oo *OnuDeviceEntry) UpdateOnuUniTpPath(ctx context.Context, aUniID uint8, aTpID uint8, aPathString string) bool {
+ /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
+ as also the complete sequence is ensured to 'run to completion' before some new request is accepted
+ no specific concurrency protection to SOnuPersistentData is required here
+ */
+ oo.MutexPersOnuConfig.Lock()
+ defer oo.MutexPersOnuConfig.Unlock()
+
+ for k, v := range oo.SOnuPersistentData.PersUniConfig {
+ if v.PersUniID == aUniID {
+ existingPath, ok := oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID]
+ logger.Debugw(ctx, "PersUniConfig-entry exists", log.Fields{"device-id": oo.deviceID, "uniID": aUniID,
+ "tpID": aTpID, "path": aPathString, "existingPath": existingPath, "ok": ok})
+ if !ok {
+ logger.Debugw(ctx, "tp-does-not-exist", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "tpID": aTpID, "path": aPathString})
+ }
+ if existingPath != aPathString {
+ if aPathString == "" {
+ //existing entry to be deleted
+ logger.Debugw(ctx, "UniTp delete path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+ oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = ""
+ } else {
+ //existing entry to be modified
+ logger.Debugw(ctx, "UniTp modify path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+ oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = aPathString
+ }
+ return true
+ }
+ //entry already exists
+ if aPathString == "" {
+ //no active TechProfile
+ logger.Debugw(ctx, "UniTp path has already been removed - no AniSide config to be removed", log.Fields{
+ "device-id": oo.deviceID, "uniID": aUniID})
+ } else {
+ //the given TechProfile already exists and is assumed to be active - update devReason as if the config has been done here
+ //was needed e.g. in voltha POD Tests:Validate authentication on a disabled ONU
+ // (as here the TechProfile has not been removed with the disable-device before the new enable-device)
+ logger.Debugw(ctx, "UniTp path already exists - TechProfile supposed to be active", log.Fields{
+ "device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+ //no deviceReason update (DeviceProcStatusUpdate) here to ensure 'omci_flows_pushed' state within disable/enable procedure of ATT scenario
+ // (during which the flows are removed/re-assigned but the techProf is left active)
+ //and as the TechProfile is regarded as active we have to verify, if some flow configuration still waits on it
+ // (should not be the case, but should not harm or be more robust ...)
+ // and to be sure, that for some reason the corresponding TpDelete was lost somewhere in history
+ // we also reset a possibly outstanding delete request - repeated TpConfig is regarded as valid for waiting flow config
+ if oo.pOnuTP != nil {
+ oo.pOnuTP.SetProfileToDelete(aUniID, aTpID, false)
+ }
+ go oo.baseDeviceHandler.VerifyVlanConfigRequest(ctx, aUniID, aTpID)
+ }
+ return false //indicate 'no change' - nothing more to do, TechProf inter-adapter message is return with success anyway here
+ }
+ }
+ //no entry exists for uniId
+
+ if aPathString == "" {
+ //delete request in non-existing state , accept as no change
+ logger.Debugw(ctx, "UniTp path already removed", log.Fields{"device-id": oo.deviceID, "uniID": aUniID})
+ return false
+ }
+ //new entry to be created
+ logger.Debugw(ctx, "New UniTp path set", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+ perSubTpPathMap := make(map[uint8]string)
+ perSubTpPathMap[aTpID] = aPathString
+ oo.SOnuPersistentData.PersUniConfig =
+ append(oo.SOnuPersistentData.PersUniConfig, uniPersConfig{PersUniID: aUniID, PersTpPathMap: perSubTpPathMap, PersFlowParams: make([]cmn.UniVlanFlowParams, 0)})
+ return true
+}
+
+// UpdateOnuUniFlowConfig - TODO: add comment
+func (oo *OnuDeviceEntry) UpdateOnuUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]cmn.UniVlanFlowParams) {
+
+ oo.MutexPersOnuConfig.Lock()
+ defer oo.MutexPersOnuConfig.Unlock()
+
+ for k, v := range oo.SOnuPersistentData.PersUniConfig {
+ if v.PersUniID == aUniID {
+ oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams = make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))
+ copy(oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams, *aUniVlanFlowParams)
+ return
+ }
+ }
+ //flow update was faster than tp-config - create PersUniConfig-entry
+ //TODO!!: following activity to 'add' some new uni entry might not be quite correct if this function is called to clear the data
+ // (e.g after flow removal from RemoveUniFlowParams()).
+ // This has the effect of misleading indication that there is still some active UNI entry, even though there might be only some nil flow entry
+ // The effect of this flaw is that at TechProfile removal there is an additional attempt to remove the entry even though no techProfile exists anymore
+ // The code is not changed here because of the current release lane, changes might have unexpected secondary effects, perhaps later with more elaborate tests
+ tmpConfig := uniPersConfig{PersUniID: aUniID, PersTpPathMap: make(map[uint8]string), PersFlowParams: make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))}
+ copy(tmpConfig.PersFlowParams, *aUniVlanFlowParams)
+ oo.SOnuPersistentData.PersUniConfig = append(oo.SOnuPersistentData.PersUniConfig, tmpConfig)
+}
+
+func (oo *OnuDeviceEntry) waitForTimeoutOrCompletion(
+ ctx context.Context, aChOnuProcessingStep <-chan uint8, aProcessingStep uint8) bool {
+ select {
+ case <-ctx.Done():
+ logger.Warnw(ctx, "processing not completed in-time!",
+ log.Fields{"device-id": oo.deviceID, "error": ctx.Err()})
+ return false
+ case rxStep := <-aChOnuProcessingStep:
+ if rxStep == aProcessingStep {
+ return true
+ }
+ //all other values are not accepted - including 0 for error indication
+ logger.Warnw(ctx, "Invalid processing step received: abort!",
+ log.Fields{"device-id": oo.deviceID,
+ "wantedStep": aProcessingStep, "haveStep": rxStep})
+ return false
+ }
+}
+
+// ResetKvProcessingErrorIndication - TODO: add comment
+func (oo *OnuDeviceEntry) ResetKvProcessingErrorIndication() {
+ oo.mutexOnuKVStoreProcResult.Lock()
+ oo.onuKVStoreProcResult = nil
+ oo.mutexOnuKVStoreProcResult.Unlock()
+}
+
+// GetKvProcessingErrorIndication - TODO: add comment
+func (oo *OnuDeviceEntry) GetKvProcessingErrorIndication() error {
+ oo.mutexOnuKVStoreProcResult.RLock()
+ value := oo.onuKVStoreProcResult
+ oo.mutexOnuKVStoreProcResult.RUnlock()
+ return value
+}
+
+func (oo *OnuDeviceEntry) setKvProcessingErrorIndication(value error) {
+ oo.mutexOnuKVStoreProcResult.Lock()
+ oo.onuKVStoreProcResult = value
+ oo.mutexOnuKVStoreProcResult.Unlock()
+}
+
+// IncrementMibDataSync - TODO: add comment
+func (oo *OnuDeviceEntry) IncrementMibDataSync(ctx context.Context) {
+ oo.MutexPersOnuConfig.Lock()
+ defer oo.MutexPersOnuConfig.Unlock()
+ if oo.SOnuPersistentData.PersMibDataSyncAdpt < 255 {
+ oo.SOnuPersistentData.PersMibDataSyncAdpt++
+ } else {
+ // per G.984 and G.988 overflow starts over at 1 given 0 is reserved for reset
+ oo.SOnuPersistentData.PersMibDataSyncAdpt = 1
+ }
+ logger.Debugf(ctx, "mibDataSync updated - mds: %d - device-id: %s", oo.SOnuPersistentData.PersMibDataSyncAdpt, oo.deviceID)
+}
+
+// ModifySwImageInactiveVersion - updates the inactive SW image version stored
+func (oo *OnuDeviceEntry) ModifySwImageInactiveVersion(ctx context.Context, aImageVersion string) {
+ oo.mutexOnuSwImageIndications.Lock()
+ defer oo.mutexOnuSwImageIndications.Unlock()
+ logger.Debugw(ctx, "software-image set inactive version", log.Fields{
+ "device-id": oo.deviceID, "version": aImageVersion})
+ oo.onuSwImageIndications.InActiveEntityEntry.Version = aImageVersion
+ //inactive SW version is not part of persistency data (yet) - no need to update that
+}
+
+// ModifySwImageActiveCommit - updates the active SW commit flag stored
+func (oo *OnuDeviceEntry) ModifySwImageActiveCommit(ctx context.Context, aCommitted uint8) {
+ oo.mutexOnuSwImageIndications.Lock()
+ defer oo.mutexOnuSwImageIndications.Unlock()
+ logger.Debugw(ctx, "software-image set active entity commit flag", log.Fields{
+ "device-id": oo.deviceID, "committed": aCommitted})
+ oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = aCommitted
+ //commit flag is not part of persistency data (yet) - no need to update that
+}
+
+// GetActiveImageVersion - returns the active SW image version stored
+func (oo *OnuDeviceEntry) GetActiveImageVersion(ctx context.Context) string {
+ oo.mutexOnuSwImageIndications.RLock()
+ if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+ value := oo.onuSwImageIndications.ActiveEntityEntry.Version
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return value
+ }
+ oo.mutexOnuSwImageIndications.RUnlock()
+ logger.Debugw(ctx, "Active Image is not valid", log.Fields{"device-id": oo.deviceID})
+ return ""
+}
+
+// GetInactiveImageVersion - TODO: add comment
+func (oo *OnuDeviceEntry) GetInactiveImageVersion(ctx context.Context) string {
+ oo.mutexOnuSwImageIndications.RLock()
+ if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
+ value := oo.onuSwImageIndications.InActiveEntityEntry.Version
+ oo.mutexOnuSwImageIndications.RUnlock()
+ return value
+ }
+ oo.mutexOnuSwImageIndications.RUnlock()
+ logger.Debugw(ctx, "Inactive Image is not valid", log.Fields{"device-id": oo.deviceID})
+ return ""
+}
+
+func (oo *OnuDeviceEntry) buildMibTemplatePath() string {
+ oo.MutexPersOnuConfig.RLock()
+ defer oo.MutexPersOnuConfig.RUnlock()
+ return fmt.Sprintf(cSuffixMibTemplateKvStore, oo.SOnuPersistentData.PersVendorID, oo.SOnuPersistentData.PersEquipmentID, oo.SOnuPersistentData.PersActiveSwVersion)
+}
+
+// AllocateFreeTcont - TODO: add comment
+func (oo *OnuDeviceEntry) AllocateFreeTcont(ctx context.Context, allocID uint16) (uint16, bool, error) {
+ logger.Debugw(ctx, "allocate-free-tcont", log.Fields{"device-id": oo.deviceID, "allocID": allocID,
+ "allocated-instances": oo.SOnuPersistentData.PersTcontMap})
+
+ oo.mutexTcontMap.Lock()
+ defer oo.mutexTcontMap.Unlock()
+ if entityID, ok := oo.SOnuPersistentData.PersTcontMap[allocID]; ok {
+ //tcont already allocated before, return the used instance-id
+ return entityID, true, nil
+ }
+ //First allocation of tcont. Find a free instance
+ if tcontInstKeys := oo.pOnuDB.GetSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
+ logger.Debugw(ctx, "allocate-free-tcont-db-keys", log.Fields{"device-id": oo.deviceID, "keys": tcontInstKeys})
+ for _, instID := range tcontInstKeys {
+ instExist := false
+ //If this instance exist in map, it means it is not empty. It is allocated before
+ for _, v := range oo.SOnuPersistentData.PersTcontMap {
+ if v == instID {
+ instExist = true
+ break
+ }
+ }
+ if !instExist {
+ oo.SOnuPersistentData.PersTcontMap[allocID] = instID
+ return instID, false, nil
+ }
+ }
+ }
+ return 0, false, fmt.Errorf(fmt.Sprintf("no-free-tcont-left-for-device-%s", oo.deviceID))
+
+}
+
+// FreeTcont - TODO: add comment
+func (oo *OnuDeviceEntry) FreeTcont(ctx context.Context, allocID uint16) {
+ logger.Debugw(ctx, "free-tcont", log.Fields{"device-id": oo.deviceID, "alloc": allocID})
+ oo.mutexTcontMap.Lock()
+ defer oo.mutexTcontMap.Unlock()
+ delete(oo.SOnuPersistentData.PersTcontMap, allocID)
+}
+
+// GetDevOmciCC - TODO: add comment
+func (oo *OnuDeviceEntry) GetDevOmciCC() *cmn.OmciCC {
+ return oo.PDevOmciCC
+}
+
+// GetOnuDB - TODO: add comment
+func (oo *OnuDeviceEntry) GetOnuDB() *devdb.OnuDeviceDB {
+ return oo.pOnuDB
+}
+
+// GetPersSerialNumber - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersSerialNumber() string {
+ value := oo.SOnuPersistentData.PersSerialNumber
+ return value
+}
+
+// GetPersVendorID - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersVendorID() string {
+ value := oo.SOnuPersistentData.PersVendorID
+ return value
+}
+
+// GetPersEquipmentID - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersEquipmentID() string {
+ value := oo.SOnuPersistentData.PersEquipmentID
+ return value
+}
+
+// GetMibUploadFsmCommChan - TODO: add comment
+func (oo *OnuDeviceEntry) GetMibUploadFsmCommChan() chan cmn.Message {
+ return oo.PMibUploadFsm.CommChan
+}
+
+// GetMibDownloadFsmCommChan - TODO: add comment
+func (oo *OnuDeviceEntry) GetMibDownloadFsmCommChan() chan cmn.Message {
+ return oo.PMibDownloadFsm.CommChan
+}
+
+// GetOmciRebootMsgRevChan - TODO: add comment
+func (oo *OnuDeviceEntry) GetOmciRebootMsgRevChan() chan cmn.Message {
+ return oo.omciRebootMessageReceivedChannel
+}
+
+// LockMutexOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) LockMutexOnuSwImageIndications() {
+ oo.mutexOnuSwImageIndications.Lock()
+}
+
+// UnlockMutexOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) UnlockMutexOnuSwImageIndications() {
+ oo.mutexOnuSwImageIndications.Unlock()
+}
+
+// GetOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) GetOnuSwImageIndications() cmn.SswImageIndications {
+ return oo.onuSwImageIndications
+}
+
+// SetOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) SetOnuSwImageIndications(value cmn.SswImageIndications) {
+ oo.onuSwImageIndications = value
+}
+
+// LockMutexPersOnuConfig - TODO: add comment
+func (oo *OnuDeviceEntry) LockMutexPersOnuConfig() {
+ oo.MutexPersOnuConfig.Lock()
+}
+
+// UnlockMutexPersOnuConfig - TODO: add comment
+func (oo *OnuDeviceEntry) UnlockMutexPersOnuConfig() {
+ oo.MutexPersOnuConfig.Unlock()
+}
+
+// GetPersActiveSwVersion - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersActiveSwVersion() string {
+ return oo.SOnuPersistentData.PersActiveSwVersion
+}
+
+// SetPersActiveSwVersion - TODO: add comment
+func (oo *OnuDeviceEntry) SetPersActiveSwVersion(value string) {
+ oo.SOnuPersistentData.PersActiveSwVersion = value
+}
+
+// SetReconcilingFlows - TODO: add comment
+func (oo *OnuDeviceEntry) SetReconcilingFlows(value bool) {
+ oo.mutexReconcilingFlowsFlag.Lock()
+ oo.reconcilingFlows = value
+ oo.mutexReconcilingFlowsFlag.Unlock()
+}
+
+// SetChReconcilingFlowsFinished - TODO: add comment
+func (oo *OnuDeviceEntry) SetChReconcilingFlowsFinished(value bool) {
+ oo.chReconcilingFlowsFinished <- value
+}
+
+// IsReconcilingFlows - TODO: add comment
+func (oo *OnuDeviceEntry) IsReconcilingFlows() bool {
+ oo.mutexReconcilingFlowsFlag.RLock()
+ value := oo.reconcilingFlows
+ oo.mutexReconcilingFlowsFlag.RUnlock()
+ return value
+}