VOL-3052 Onu Software preliminary upgrade extensions with internal test, version 1.2.5-dev171
Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I23ee1a14af635def33b565444f1a1f81370a86a7
diff --git a/VERSION b/VERSION
index cc63d17..7585f69 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.5-dev170
+1.2.5-dev171
diff --git a/go.mod b/go.mod
index b6adf67..81f8227 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@
github.com/golang/protobuf v1.4.2
github.com/google/gopacket v1.1.17
github.com/looplab/fsm v0.1.0
- github.com/opencord/omci-lib-go v0.15.2
+ github.com/opencord/omci-lib-go v0.15.4
github.com/opencord/voltha-lib-go/v4 v4.0.10
github.com/opencord/voltha-protos/v4 v4.0.13
github.com/stretchr/testify v1.6.1
diff --git a/go.sum b/go.sum
index b7529f3..a0fd282 100644
--- a/go.sum
+++ b/go.sum
@@ -160,8 +160,8 @@
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/opencord/omci-lib-go v0.15.2 h1:RVqjVI0RvWlJb+n8NMWrIDt2J+o5L7JNkHZdHjpMLws=
-github.com/opencord/omci-lib-go v0.15.2/go.mod h1:6OIHB14Ch5qGgHzwSWlMACtk5KFoLzQ4LAhdcy4jwvo=
+github.com/opencord/omci-lib-go v0.15.4 h1:g+IkuCZeS7Okvm7TxjobaLwX6UHo26hCvdyyqX9Bfi8=
+github.com/opencord/omci-lib-go v0.15.4/go.mod h1:6OIHB14Ch5qGgHzwSWlMACtk5KFoLzQ4LAhdcy4jwvo=
github.com/opencord/voltha-lib-go/v4 v4.0.10 h1:mSi9e3TD+liit5NbV+AKEJ2dza3n+DpzdExJog2LtTo=
github.com/opencord/voltha-lib-go/v4 v4.0.10/go.mod h1:K7lDkSkJ97EyfvX8fQtBmBvpj7n6MmwnAtD8Jz79HcQ=
github.com/opencord/voltha-protos/v4 v4.0.12 h1:x8drb8inaUByjVLFbXSiQwRTU//dfde0MKIHyKb1JMw=
@@ -209,6 +209,7 @@
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -312,6 +313,7 @@
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd h1:hHkvGJK23seRCflePJnVa9IMv8fsuavSCWKd11kDQFs=
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
diff --git a/internal/pkg/onuadaptercore/adapter_download_manager.go b/internal/pkg/onuadaptercore/adapter_download_manager.go
index aaaacd6..3db9cc7 100644
--- a/internal/pkg/onuadaptercore/adapter_download_manager.go
+++ b/internal/pkg/onuadaptercore/adapter_download_manager.go
@@ -20,6 +20,7 @@
import (
"bufio"
"context"
+ "errors"
"os"
"sync"
@@ -95,23 +96,27 @@
//startDownload returns true if the download of the requested image could be started
func (dm *adapterDownloadManager) startDownload(ctx context.Context, apImageDsc *voltha.ImageDownload) error {
- logger.Warnw(ctx, "image download requested - but not yet processed", log.Fields{"image-name": apImageDsc.Name})
- newImageDscPos := len(dm.downloadImageDscSlice)
- dm.downloadImageDscSlice = append(dm.downloadImageDscSlice, apImageDsc)
- dm.downloadImageDscSlice[newImageDscPos].DownloadState = voltha.ImageDownload_DOWNLOAD_STARTED
- //just some basic test file simulation
- go dm.writeFileToLFS(ctx, apImageDsc.Name, apImageDsc.LocalDir)
- //return success to comfort the core processing during integration
- return nil
- // TODO!!: also verify error response behavior
- //return fmt.Errorf("onuSwUpgrade not yet implemented")
+ if apImageDsc.LocalDir != "" {
+ logger.Infow(ctx, "image download-to-adapter requested", log.Fields{"image-name": apImageDsc.Name})
+ newImageDscPos := len(dm.downloadImageDscSlice)
+ dm.downloadImageDscSlice = append(dm.downloadImageDscSlice, apImageDsc)
+ dm.downloadImageDscSlice[newImageDscPos].DownloadState = voltha.ImageDownload_DOWNLOAD_STARTED
+ //just some basic test file simulation
+ go dm.writeFileToLFS(ctx, apImageDsc.Name, apImageDsc.LocalDir)
+ //return success to comfort the core processing during integration
+ return nil
+ }
+ // we can use the missing local path temporary also to test some failure behavior (system reation on failure)
+ // with updated control API's or at some adequate time we could also set some defined fixed localPath internally
+ logger.Errorw(ctx, "could not start download: no valid local directory to write to", log.Fields{"image-name": (*apImageDsc).Name})
+ return errors.New("could not start download: no valid local directory to write to")
}
//writeFileToLFS writes the downloaded file to the local file system
func (dm *adapterDownloadManager) writeFileToLFS(ctx context.Context, aFileName string, aLocalPath string) {
// by now just a simulation to write a file with predefined 'variable' content
totalFileLength := 0
- logger.Debugw(ctx, "Writing fixed size simulation file locally", log.Fields{
+ logger.Debugw(ctx, "writing fixed size simulation file locally", log.Fields{
"image-name": aFileName, "image-path": aLocalPath})
file, err := os.Create(aLocalPath + "/" + aFileName)
if err == nil {
@@ -120,19 +125,19 @@
if written, wrErr := file.Write(dm.getIncrementalSliceContent(ctx)); wrErr == nil {
totalFileLength += written
} else {
- logger.Errorw(ctx, "Could not write to file", log.Fields{"create-error": wrErr})
+ logger.Errorw(ctx, "could not write to file", log.Fields{"create-error": wrErr})
break //stop writing
}
}
} else {
- logger.Errorw(ctx, "Could not create file", log.Fields{"create-error": err})
+ logger.Errorw(ctx, "could not create file", log.Fields{"create-error": err})
}
fileStats, statsErr := file.Stat()
if err != nil {
logger.Errorw(ctx, "created file can't be accessed", log.Fields{"stat-error": statsErr})
}
- logger.Debugw(ctx, "Written file size is", log.Fields{"length": fileStats.Size()})
+ logger.Infow(ctx, "written file size is", log.Fields{"file": aLocalPath + "/" + aFileName, "length": fileStats.Size()})
//nolint:gosec,errcheck
file.Close()
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index 556fe62..6c4d5ce 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -936,16 +936,20 @@
return pDevEntry.getKvProcessingErrorIndication()
}
-func (dh *deviceHandler) rebootDevice(ctx context.Context, device *voltha.Device) error {
- logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
- if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
+//func (dh *deviceHandler) rebootDevice(ctx context.Context, device *voltha.Device) error {
+// before this change here return like this was used:
+// return fmt.Errorf("device-unreachable: %s, %s", dh.deviceID, device.SerialNumber)
+//was and is called in background - error return does not make sense
+func (dh *deviceHandler) rebootDevice(ctx context.Context, aCheckDeviceState bool, device *voltha.Device) {
+ logger.Infow(ctx, "reboot-device", log.Fields{"device-id": dh.deviceID, "SerialNumber": dh.device.SerialNumber})
+ if aCheckDeviceState && device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
logger.Errorw(ctx, "device-unreachable", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
- return fmt.Errorf("device-unreachable: %s, %s", dh.deviceID, device.SerialNumber)
+ return
}
if err := dh.pOnuOmciDevice.reboot(log.WithSpanFromContext(context.TODO(), ctx)); err != nil {
//TODO with VOL-3045/VOL-3046: return the error and stop further processing
logger.Errorw(ctx, "error-rebooting-device", log.Fields{"device-id": dh.deviceID, "error": err})
- return err
+ return
}
//transfer the possibly modified logical uni port state
@@ -957,17 +961,16 @@
voltha.OperStatus_DISCOVERED); err != nil {
//TODO with VOL-3045/VOL-3046: return the error and stop further processing
logger.Errorw(ctx, "error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
- return err
+ return
}
if err := dh.deviceReasonUpdate(ctx, drRebooting, true); err != nil {
- return err
+ return
}
dh.ReadyForSpecificOmciConfig = false
//no specific activity to synchronize any internal FSM to the 'rebooted' state is explicitly done here
// the expectation ids for a real device, that it will be synced with the expected following 'down' indication
// as BBSIM does not support this testing requires explicite disable/enable device calls in which sequence also
// all other FSM's should be synchronized again
- return nil
}
//doOnuSwUpgrade initiates the SW download transfer to the ONU and on success activates the (inactive) image
@@ -977,39 +980,52 @@
"device-id": dh.deviceID, "image-name": (*apImageDsc).Name})
var err error
+ pDevEntry := dh.getOnuDeviceEntry(ctx, true)
+ if pDevEntry == nil {
+ logger.Errorw(ctx, "start Onu SW upgrade rejected: no valid OnuDevice", log.Fields{"device-id": dh.deviceID})
+ return fmt.Errorf("start Onu SW upgrade rejected: no valid OnuDevice for device-id: %s", dh.deviceID)
+ }
+
if dh.ReadyForSpecificOmciConfig {
- dh.lockUpgradeFsm.Lock()
- defer dh.lockUpgradeFsm.Unlock()
- if dh.pOnuUpradeFsm == nil {
- err = dh.createOnuUpgradeFsm(ctx, OmciOnuSwUpgradeDone)
- if err == nil {
- if err = dh.pOnuUpradeFsm.SetDownloadParams(ctx, apImageDsc, apDownloadManager); err != nil {
- logger.Errorw(ctx, "onu upgrade fsm could not set parameters", log.Fields{
+ var inactiveImageID uint16
+ if inactiveImageID, err = pDevEntry.GetInactiveImageMeID(ctx); err == nil {
+ dh.lockUpgradeFsm.Lock()
+ defer dh.lockUpgradeFsm.Unlock()
+ if dh.pOnuUpradeFsm == nil {
+ err = dh.createOnuUpgradeFsm(ctx, pDevEntry, OmciOnuSwUpgradeDone)
+ if err == nil {
+ if err = dh.pOnuUpradeFsm.SetDownloadParams(ctx, inactiveImageID, apImageDsc, apDownloadManager); err != nil {
+ logger.Errorw(ctx, "onu upgrade fsm could not set parameters", log.Fields{
+ "device-id": dh.deviceID, "error": err})
+ }
+ } else {
+ logger.Errorw(ctx, "onu upgrade fsm could not be created", log.Fields{
"device-id": dh.deviceID, "error": err})
}
- } else {
- logger.Errorw(ctx, "onu upgrade fsm could not be created", log.Fields{
- "device-id": dh.deviceID, "error": err})
- }
- } else { //OnuSw upgrade already running - restart (with possible abort of running)
- logger.Debugw(ctx, "Onu SW upgrade already running - abort", log.Fields{"device-id": dh.deviceID})
- pUpgradeStatemachine := dh.pOnuUpradeFsm.pAdaptFsm.pFsm
- if pUpgradeStatemachine != nil {
- if err = pUpgradeStatemachine.Event(upgradeEvAbort); err != nil {
- logger.Errorw(ctx, "onu upgrade fsm could not abort a running processing", log.Fields{
- "device-id": dh.deviceID, "error": err})
+ } else { //OnuSw upgrade already running - restart (with possible abort of running)
+ logger.Debugw(ctx, "Onu SW upgrade already running - abort", log.Fields{"device-id": dh.deviceID})
+ pUpgradeStatemachine := dh.pOnuUpradeFsm.pAdaptFsm.pFsm
+ if pUpgradeStatemachine != nil {
+ if err = pUpgradeStatemachine.Event(upgradeEvAbort); err != nil {
+ logger.Errorw(ctx, "onu upgrade fsm could not abort a running processing", log.Fields{
+ "device-id": dh.deviceID, "error": err})
+ }
+ err = fmt.Errorf("aborted Onu SW upgrade but not automatically started, try again, device-id: %s", dh.deviceID)
+ //TODO!!!: wait for 'ready' to start and configure - see above SetDownloadParams()
+ // for now a second start of download should work again
+ } else { //should never occur
+ logger.Errorw(ctx, "onu upgrade fsm inconsistent setup", log.Fields{
+ "device-id": dh.deviceID})
+ err = fmt.Errorf("onu upgrade fsm inconsistent setup, baseFsm invalid for device-id: %s", dh.deviceID)
}
- err = fmt.Errorf("aborted Onu SW upgrade but not automatically started, try again, device-id: %s", dh.deviceID)
- //TODO!!!: wait for 'ready' to start and configure - see above SetDownloadParams()
- // for now a second start of download should work again
- } else { //should never occur
- logger.Errorw(ctx, "onu upgrade fsm inconsistent setup", log.Fields{
- "device-id": dh.deviceID})
- err = fmt.Errorf("onu upgrade fsm inconsistent setup, baseFsm invalid for device-id: %s", dh.deviceID)
}
+ } else {
+ logger.Errorw(ctx, "start Onu SW upgrade rejected: no inactive image", log.Fields{
+ "device-id": dh.deviceID, "error": err})
}
} else {
- logger.Errorw(ctx, "Start Onu SW upgrade rejected: no active OMCI connection", log.Fields{"device-id": dh.deviceID})
+ logger.Errorw(ctx, "start Onu SW upgrade rejected: no active OMCI connection", log.Fields{"device-id": dh.deviceID})
+ err = fmt.Errorf("start Onu SW upgrade rejected: no active OMCI connection for device-id: %s", dh.deviceID)
}
return err
}
@@ -1753,6 +1769,10 @@
if !dh.isReconciling() {
logger.Debugw(ctx, "call DeviceStateUpdate upon mib-download done", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
"OperStatus": voltha.OperStatus_ACTIVE, "device-id": dh.deviceID})
+ //we allow a possible OnuSw image commit only in the normal startup, not at reconciling
+ // in case of adapter restart connected to an ONU upgrade I would not rely on the image quality
+ // maybe some 'forced' commitment can be done in this situation from system management (or upgrade restarted)
+ dh.checkOnOnuImageCommit(ctx)
if err := dh.coreProxy.DeviceStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.deviceID,
voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
//TODO with VOL-3045/VOL-3046: return the error and stop further processing
@@ -2160,17 +2180,16 @@
}
// createOnuUpgradeFsm initializes and runs the Onu Software upgrade FSM
-func (dh *deviceHandler) createOnuUpgradeFsm(ctx context.Context, devEvent OnuDeviceEvent) error {
+func (dh *deviceHandler) createOnuUpgradeFsm(ctx context.Context, apDevEntry *OnuDeviceEntry, aDevEvent OnuDeviceEvent) error {
//in here lockUpgradeFsm is already locked
chUpgradeFsm := make(chan Message, 2048)
var sFsmName = "OnuSwUpgradeFSM"
logger.Debugw(ctx, "create OnuSwUpgradeFSM", log.Fields{"device-id": dh.deviceID})
- pDevEntry := dh.getOnuDeviceEntry(ctx, true)
- if pDevEntry == nil {
- logger.Errorw(ctx, "no valid OnuDevice -abort", log.Fields{"device-id": dh.deviceID})
- return fmt.Errorf(fmt.Sprintf("no valid OnuDevice - abort for device-id: %s", dh.device.Id))
+ if apDevEntry.PDevOmciCC == nil {
+ logger.Errorw(ctx, "no valid OnuDevice or omciCC - abort", log.Fields{"device-id": dh.deviceID})
+ return fmt.Errorf(fmt.Sprintf("no valid omciCC - abort for device-id: %s", dh.device.Id))
}
- dh.pOnuUpradeFsm = NewOnuUpgradeFsm(ctx, dh, pDevEntry.PDevOmciCC, pDevEntry.pOnuDB, devEvent,
+ dh.pOnuUpradeFsm = NewOnuUpgradeFsm(ctx, dh, apDevEntry, apDevEntry.pOnuDB, aDevEvent,
sFsmName, chUpgradeFsm)
if dh.pOnuUpradeFsm != nil {
pUpgradeStatemachine := dh.pOnuUpradeFsm.pAdaptFsm.pFsm
@@ -2211,6 +2230,43 @@
dh.pOnuUpradeFsm = nil //resource clearing is left to garbage collector
}
+// checkOnOnuImageCommit verifies if the ONU is in some upgrade state that allows for image commit and if tries to commit
+func (dh *deviceHandler) checkOnOnuImageCommit(ctx context.Context) {
+ pDevEntry := dh.getOnuDeviceEntry(ctx, false)
+ if pDevEntry == nil {
+ logger.Errorw(ctx, "No valid OnuDevice -aborting checkOnOnuImageCommit", log.Fields{"device-id": dh.deviceID})
+ return
+ }
+
+ dh.lockUpgradeFsm.RLock()
+ defer dh.lockUpgradeFsm.RUnlock()
+ if dh.pOnuUpradeFsm != nil {
+ pUpgradeStatemachine := dh.pOnuUpradeFsm.pAdaptFsm.pFsm
+ if pUpgradeStatemachine != nil {
+ // commit is only processed in case out upgrade FSM indicates the according state (for automatic commit)
+ // (some manual forced commit could do without)
+ if pUpgradeStatemachine.Is(upgradeStWaitForCommit) {
+ forcedTest := true //TODO!!: needed as long as BBSIM does not fully support SW upgrade simulation
+ if forcedTest || pDevEntry.IsImageToBeCommitted(ctx, dh.pOnuUpradeFsm.inactiveImageMeID) {
+ if err := pUpgradeStatemachine.Event(upgradeEvCommitSw); err != nil {
+ logger.Errorw(ctx, "OnuSwUpgradeFSM: can't call commit event", log.Fields{"err": err})
+ return
+ }
+ logger.Debugw(ctx, "OnuSwUpgradeFSM commit image requested", log.Fields{
+ "state": pUpgradeStatemachine.Current(), "device-id": dh.deviceID})
+ } else {
+ logger.Errorw(ctx, "OnuSwUpgradeFSM waiting to commit, but nothing to commit on ONU - abort upgrade",
+ log.Fields{"device-id": dh.deviceID})
+ _ = pUpgradeStatemachine.Event(upgradeEvAbort)
+ return
+ }
+ }
+ }
+ } else {
+ logger.Debugw(ctx, "no ONU image to be committed", log.Fields{"device-id": dh.deviceID})
+ }
+}
+
//setBackend provides a DB backend for the specified path on the existing KV client
func (dh *deviceHandler) setBackend(ctx context.Context, aBasePathKvStore string) *db.Backend {
@@ -2760,6 +2816,7 @@
}
}
logger.Infow(ctx, "handling-global-pm-config-params - done", log.Fields{"device-id": dh.device.Id})
+
return errorsList
}
diff --git a/internal/pkg/onuadaptercore/mib_sync.go b/internal/pkg/onuadaptercore/mib_sync.go
index 0fcf7f9..0c71848 100644
--- a/internal/pkg/onuadaptercore/mib_sync.go
+++ b/internal/pkg/onuadaptercore/mib_sync.go
@@ -103,7 +103,7 @@
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{"IsActive": 0, "Version": ""}
+ requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
meInstance := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, firstSwImageMeID, requestedAttributes, ConstDefaultOmciTimeout, true, oo.pMibUploadFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
@@ -112,7 +112,7 @@
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{"IsActive": 0, "Version": ""}
+ requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
meInstance := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, secondSwImageMeID, requestedAttributes, ConstDefaultOmciTimeout, true, oo.pMibUploadFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
@@ -130,10 +130,11 @@
func (oo *OnuDeviceEntry) enterGettingMibTemplate(ctx context.Context, e *fsm.Event) {
- for i := firstSwImageMeID; i <= secondSwImageMeID; i++ {
- if oo.swImages[i].isActive > 0 {
- oo.activeSwVersion = oo.swImages[i].version
- }
+ if oo.onuSwImageIndications.activeEntityEntry.valid {
+ oo.activeSwVersion = oo.onuSwImageIndications.activeEntityEntry.version
+ } else {
+ 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})
}
meStoredFromTemplate := false
@@ -477,22 +478,15 @@
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetFirstSwVersion)
return nil
case "SoftwareImage":
- if entityID <= secondSwImageMeID {
- oo.swImages[entityID].version = trimStringFromInterface(meAttributes["Version"])
- oo.swImages[entityID].isActive = meAttributes["IsActive"].(uint8)
- logger.Debugw(ctx, "MibSync FSM - GetResponse Data for SoftwareImage - Version/IsActive",
- log.Fields{"device-id": oo.deviceID, "entityID": entityID,
- "version": oo.swImages[entityID].version, "isActive": oo.swImages[entityID].isActive})
- } else {
- err = fmt.Errorf("mibSync FSM - Failed to GetResponse Data for SoftwareImage: %s", oo.deviceID)
+ if entityID > 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)
}
- if firstSwImageMeID == entityID {
- _ = oo.pMibUploadFsm.pFsm.Event(ulEvGetSecondSwVersion)
- return nil
- } else if secondSwImageMeID == entityID {
- _ = oo.pMibUploadFsm.pFsm.Event(ulEvGetMacAddress)
- return nil
- }
+ // need to use function for go lint complexity
+ oo.handleSwImageIndications(ctx, entityID, meAttributes)
+ return nil
case "IpHostConfigData":
macBytes, _ := me.InterfaceToOctets(meAttributes["MacAddress"])
if omciMacAddressLen == len(macBytes) {
@@ -523,6 +517,67 @@
return err
}
+func (oo *OnuDeviceEntry) handleSwImageIndications(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap) {
+ imageIsCommitted := meAttributes["IsCommitted"].(uint8)
+ imageIsActive := meAttributes["IsActive"].(uint8)
+ imageVersion := trimStringFromInterface(meAttributes["Version"])
+ 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.serialNumber})
+ if firstSwImageMeID == entityID {
+ //always accept the state of the first image (2nd image info should not yet be available)
+ if imageIsActive == swIsActive {
+ oo.onuSwImageIndications.activeEntityEntry.entityID = entityID
+ oo.onuSwImageIndications.activeEntityEntry.valid = true
+ oo.onuSwImageIndications.activeEntityEntry.version = imageVersion
+ oo.onuSwImageIndications.activeEntityEntry.isCommitted = imageIsCommitted
+ } else {
+ oo.onuSwImageIndications.inactiveEntityEntry.entityID = entityID
+ oo.onuSwImageIndications.inactiveEntityEntry.valid = true
+ oo.onuSwImageIndications.inactiveEntityEntry.version = imageVersion
+ oo.onuSwImageIndications.inactiveEntityEntry.isCommitted = imageIsCommitted
+ }
+ _ = oo.pMibUploadFsm.pFsm.Event(ulEvGetSecondSwVersion)
+ return
+ } else if secondSwImageMeID == entityID {
+ //2nd image info might conflict with first image info, in which case we priorize first image info!
+ if imageIsActive == 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 = 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.pMibUploadFsm.pFsm.Event(ulEvGetMacAddress)
+ return
+ }
+}
+
func (oo *OnuDeviceEntry) handleOmciMessage(ctx context.Context, msg OmciMessage) {
logger.Debugw(ctx, "MibSync Msg", log.Fields{"OmciMessage received for device-id": oo.deviceID,
"msgType": msg.OmciMsg.MessageType, "msg": msg})
@@ -718,3 +773,31 @@
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) {
+ if oo.onuSwImageIndications.activeEntityEntry.valid {
+ return oo.onuSwImageIndications.activeEntityEntry.entityID, nil
+ }
+ 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) {
+ if oo.onuSwImageIndications.inactiveEntityEntry.valid {
+ return oo.onuSwImageIndications.inactiveEntityEntry.entityID, nil
+ }
+ 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 {
+ if oo.onuSwImageIndications.activeEntityEntry.valid {
+ if oo.onuSwImageIndications.activeEntityEntry.entityID == aImageID {
+ if oo.onuSwImageIndications.activeEntityEntry.isCommitted == swIsUncommitted {
+ return true
+ }
+ }
+ }
+ return false //all other case are treated as 'nothing to commit
+}
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index dcdbe1b..a1050bc 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -45,7 +45,7 @@
// ### OMCI related definitions - retrieved from Python adapter code/trace ####
//ConstDefaultOmciTimeout - Default OMCI Timeout
-const ConstDefaultOmciTimeout = 3
+const ConstDefaultOmciTimeout = 3 //seconds
const galEthernetEID = uint16(1)
const maxGemPayloadSize = uint16(48)
@@ -2515,42 +2515,44 @@
}
logger.Debug(ctx, "send StartSwDlRequest done")
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
- time.Sleep(time.Millisecond * 200) //give some response time
- respOmciLayer := &omci.OMCI{
- TransactionID: tid,
- MessageType: omci.StartSoftwareDownloadResponseType,
- // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
- // Length: 0x28, // Optional, defaults to 40 octets
- }
- response := &omci.StartSoftwareDownloadResponse{
- MeBasePacket: omci.MeBasePacket{
- EntityClass: me.SoftwareImageClassID,
- EntityInstance: aImageMeID, //inactive image
- },
- Result: 0,
- WindowSize: aDownloadWindowSize,
- NumberOfInstances: 0, //seems at the moment I can only generate 0 instances, using 1 here panics as MeResult can not be set below
- //MeResults: cannot set here: downloadResults type not exported from omci-lib!
- }
- var respOptions gopacket.SerializeOptions
- respOptions.FixLengths = true
- respBuffer := gopacket.NewSerializeBuffer()
- respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
- if respErr != nil {
- logger.Errorw(ctx, "Cannot serialize StartSwDlResponse", log.Fields{"Err": respErr,
- "device-id": oo.deviceID})
- return respErr
- }
- respPacket := respBuffer.Bytes()
- logger.Debugw(ctx, "simulate StartSwDlResponse", log.Fields{"device-id": oo.deviceID,
- "SequNo": strconv.FormatInt(int64(tid), 16),
- "InstId": strconv.FormatInt(int64(aImageMeID), 16),
- "windowSize": aDownloadWindowSize})
- go func(oo *omciCC) {
- _ = oo.receiveMessage(ctx, respPacket)
- }(oo)
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ go func() {
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+ time.Sleep(time.Millisecond * 50) //give some response time
+ respOmciLayer := &omci.OMCI{
+ TransactionID: tid,
+ MessageType: omci.StartSoftwareDownloadResponseType,
+ // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
+ // Length: 0x28, // Optional, defaults to 40 octets
+ }
+ response := &omci.StartSoftwareDownloadResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.SoftwareImageClassID,
+ EntityInstance: aImageMeID, //inactive image
+ },
+ Result: 0,
+ WindowSize: aDownloadWindowSize,
+ NumberOfInstances: 0, //seems at the moment I can only generate 0 instances, using 1 here panics as MeResult can not be set below
+ //MeResults: cannot set here: downloadResults type not exported from omci-lib!
+ }
+ var respOptions gopacket.SerializeOptions
+ respOptions.FixLengths = true
+ respBuffer := gopacket.NewSerializeBuffer()
+ respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+ if respErr != nil {
+ logger.Errorw(ctx, "Cannot serialize StartSwDlResponse", log.Fields{"Err": respErr,
+ "device-id": oo.deviceID})
+ return
+ }
+ respPacket := respBuffer.Bytes()
+ logger.Debugw(ctx, "simulate StartSwDlResponse", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16),
+ "windowSize": aDownloadWindowSize})
+ go func(oo *omciCC) {
+ _ = oo.receiveMessage(ctx, respPacket)
+ }(oo)
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ }()
return nil
}
@@ -2559,18 +2561,22 @@
tid := oo.getNextTid(highPrio)
logger.Debugw(ctx, "send DlSectionRequest:", log.Fields{"device-id": oo.deviceID,
"SequNo": strconv.FormatInt(int64(tid), 16),
- "InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16), "omci-ack": aAckRequest})
//TODO!!!: don't know by now on how to generate the possibly needed AR (or enforce it to 0) with current omci-lib
// by now just try to send it as defined by omci-lib
+ msgType := omci.DownloadSectionRequestType
+ if aAckRequest > 0 {
+ msgType = omci.DownloadSectionRequestWithResponseType
+ }
omciLayer := &omci.OMCI{
TransactionID: tid,
- MessageType: omci.DownloadSectionRequestType,
+ MessageType: msgType,
// DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
// Length: 0x28, // Optional, defaults to 40 octets
}
var localSectionData [31]byte
- copy(localSectionData[:], aSection)
+ copy(localSectionData[:], aSection) // as long as DownloadSectionRequest defines array for SectionData we need to copy into the array
request := &omci.DownloadSectionRequest{
MeBasePacket: omci.MeBasePacket{
EntityClass: me.SoftwareImageClassID,
@@ -2591,8 +2597,14 @@
}
outgoingPacket := buffer.Bytes()
+ //for initial debug purpose overrule the requested print state for some frames
+ printFrame := aPrint
+ if aAckRequest > 0 || aDownloadSectionNo == 0 {
+ printFrame = true
+ }
+
omciRxCallbackPair := callbackPair{cbKey: tid,
- cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, aPrint},
+ cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, printFrame /*aPrint*/},
}
err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
if err != nil {
@@ -2602,48 +2614,50 @@
}
logger.Debug(ctx, "send DlSectionRequest done")
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
- if aAckRequest > 0 {
- time.Sleep(time.Millisecond * 200) //give some response time
- respOmciLayer := &omci.OMCI{
- TransactionID: tid,
- MessageType: omci.DownloadSectionResponseType,
- // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
- // Length: 0x28, // Optional, defaults to 40 octets
+ go func() {
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+ if aAckRequest > 0 {
+ time.Sleep(time.Millisecond * 50) //give some response time
+ respOmciLayer := &omci.OMCI{
+ TransactionID: tid,
+ MessageType: omci.DownloadSectionResponseType,
+ // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
+ // Length: 0x28, // Optional, defaults to 40 octets
+ }
+ response := &omci.DownloadSectionResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.SoftwareImageClassID,
+ EntityInstance: aImageMeID, //inactive image
+ },
+ Result: 0,
+ SectionNumber: aDownloadSectionNo,
+ }
+ var respOptions gopacket.SerializeOptions
+ respOptions.FixLengths = true
+ respBuffer := gopacket.NewSerializeBuffer()
+ respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+ if respErr != nil {
+ logger.Errorw(ctx, "Cannot serialize DlSectionResponse", log.Fields{"Err": respErr,
+ "device-id": oo.deviceID})
+ return
+ }
+ respPacket := respBuffer.Bytes()
+ if aPrint {
+ logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16),
+ "packet": hex.EncodeToString(respPacket)})
+ } else {
+ logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+ }
+ go func(oo *omciCC) {
+ _ = oo.receiveMessage(ctx, respPacket)
+ }(oo)
}
- response := &omci.DownloadSectionResponse{
- MeBasePacket: omci.MeBasePacket{
- EntityClass: me.SoftwareImageClassID,
- EntityInstance: aImageMeID, //inactive image
- },
- Result: 0,
- SectionNumber: aDownloadSectionNo,
- }
- var respOptions gopacket.SerializeOptions
- respOptions.FixLengths = true
- respBuffer := gopacket.NewSerializeBuffer()
- respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
- if respErr != nil {
- logger.Errorw(ctx, "Cannot serialize DlSectionResponse", log.Fields{"Err": respErr,
- "device-id": oo.deviceID})
- return err
- }
- respPacket := respBuffer.Bytes()
- if aPrint {
- logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
- "SequNo": strconv.FormatInt(int64(tid), 16),
- "InstId": strconv.FormatInt(int64(aImageMeID), 16),
- "packet": hex.EncodeToString(respPacket)})
- } else {
- logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
- "SequNo": strconv.FormatInt(int64(tid), 16),
- "InstId": strconv.FormatInt(int64(aImageMeID), 16)})
- }
- go func(oo *omciCC) {
- _ = oo.receiveMessage(ctx, respPacket)
- }(oo)
- }
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ }()
return nil
}
@@ -2654,93 +2668,81 @@
"SequNo": strconv.FormatInt(int64(tid), 16),
"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
- //**** test simulation - as long as omci-lib serialize for this type is not corrected - just bypass sending *** start *****
- /*
- omciLayer := &omci.OMCI{
- TransactionID: tid,
- MessageType: omci.EndSoftwareDownloadRequestType,
- // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
- // Length: 0x28, // Optional, defaults to 40 octets
- }
- request := &omci.EndSoftwareDownloadRequest{
- MeBasePacket: omci.MeBasePacket{
- EntityClass: me.SoftwareImageClassID,
- EntityInstance: aImageMeID, //inactive image
- },
- CRC32: aImageCrc,
- ImageSize: aFileLen,
- NumberOfInstances: 1, //parallel download to multiple circuit packs not supported
- ImageInstances: []uint16{0}, //don't care for NumberOfInstances=1, but probably needed by omci-lib as in startSwDlRequest
- }
-
- var options gopacket.SerializeOptions
- options.FixLengths = true
- buffer := gopacket.NewSerializeBuffer()
- err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
- if err != nil {
- logger.Errorw(ctx, "Cannot serialize EndSwDlRequest", log.Fields{"Err": err,
- "device-id": oo.deviceID})
- return err
- }
- outgoingPacket := buffer.Bytes()
-
- omciRxCallbackPair := callbackPair{cbKey: tid,
- cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
- }
- err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
- if err != nil {
- logger.Errorw(ctx, "Cannot send EndSwDlRequest", log.Fields{"Err": err,
- "device-id": oo.deviceID})
- return err
- }
- */
- //**** test simulation - as long as omci-lib serialize for this type is not corrected - just bypass sending *** end *****
- logger.Debug(ctx, "send EndSwDlRequest done")
-
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
- //callback code necessary here only as long as sending the request is not possible
- omciRxCallbackPair := callbackPair{cbKey: tid,
- cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
- }
- oo.mutexRxSchedMap.Lock()
- oo.rxSchedulerMap[omciRxCallbackPair.cbKey] = omciRxCallbackPair.cbEntry
- oo.mutexRxSchedMap.Unlock()
- //callback code necessary here only as long as sending the request is not possible
-
- time.Sleep(time.Millisecond * 200) //give some response time
- respOmciLayer := &omci.OMCI{
+ omciLayer := &omci.OMCI{
TransactionID: tid,
- MessageType: omci.EndSoftwareDownloadResponseType,
+ MessageType: omci.EndSoftwareDownloadRequestType,
// DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
// Length: 0x28, // Optional, defaults to 40 octets
}
- response := &omci.EndSoftwareDownloadResponse{
+ request := &omci.EndSoftwareDownloadRequest{
MeBasePacket: omci.MeBasePacket{
EntityClass: me.SoftwareImageClassID,
EntityInstance: aImageMeID, //inactive image
},
- Result: 0, //simulate done, option would be busy
- NumberOfInstances: 0, //seems at the moment I can only generate 0 instances, using 1 here panics as MeResult can not be set below
- //MeResults: cannot set here: downloadResults type not exported from omci-lib!
+ CRC32: aImageCrc,
+ ImageSize: aFileLen,
+ NumberOfInstances: 1, //parallel download to multiple circuit packs not supported
+ ImageInstances: []uint16{0}, //don't care for NumberOfInstances=1, but probably needed by omci-lib as in startSwDlRequest
}
- var respOptions gopacket.SerializeOptions
- respOptions.FixLengths = true
- respBuffer := gopacket.NewSerializeBuffer()
- respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
- if respErr != nil {
- logger.Errorw(ctx, "Cannot serialize EndSwDlResponse", log.Fields{"Err": respErr,
+
+ var options gopacket.SerializeOptions
+ options.FixLengths = true
+ buffer := gopacket.NewSerializeBuffer()
+ err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+ if err != nil {
+ logger.Errorw(ctx, "Cannot serialize EndSwDlRequest", log.Fields{"Err": err,
"device-id": oo.deviceID})
- return respErr
+ return err
}
- respPacket := respBuffer.Bytes()
- logger.Debugw(ctx, "simulate EndSwDlResponse", log.Fields{"device-id": oo.deviceID,
- "SequNo": strconv.FormatInt(int64(tid), 16),
- "InstId": strconv.FormatInt(int64(aImageMeID), 16),
- "result": 0})
- go func(oo *omciCC) {
- _ = oo.receiveMessage(ctx, respPacket)
- }(oo)
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ outgoingPacket := buffer.Bytes()
+
+ omciRxCallbackPair := callbackPair{cbKey: tid,
+ cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
+ }
+ err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw(ctx, "Cannot send EndSwDlRequest", log.Fields{"Err": err,
+ "device-id": oo.deviceID})
+ return err
+ }
+ logger.Debug(ctx, "send EndSwDlRequest done")
+
+ go func() {
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+ time.Sleep(time.Millisecond * 50) //give some response time
+ respOmciLayer := &omci.OMCI{
+ TransactionID: tid,
+ MessageType: omci.EndSoftwareDownloadResponseType,
+ // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
+ // Length: 0x28, // Optional, defaults to 40 octets
+ }
+ response := &omci.EndSoftwareDownloadResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.SoftwareImageClassID,
+ EntityInstance: aImageMeID, //inactive image
+ },
+ Result: 0, //simulate done, option would be busy
+ NumberOfInstances: 0, //basic ONU-G instance
+ }
+ var respOptions gopacket.SerializeOptions
+ respOptions.FixLengths = true
+ respBuffer := gopacket.NewSerializeBuffer()
+ respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+ if respErr != nil {
+ logger.Errorw(ctx, "Cannot serialize EndSwDlResponse", log.Fields{"Err": respErr,
+ "device-id": oo.deviceID})
+ return
+ }
+ respPacket := respBuffer.Bytes()
+ logger.Debugw(ctx, "simulate EndSwDlResponse", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16),
+ "result": 0})
+ go func(oo *omciCC) {
+ _ = oo.receiveMessage(ctx, respPacket)
+ }(oo)
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ }()
return nil
}
@@ -2787,41 +2789,122 @@
}
logger.Debug(ctx, "send ActivateSwRequest done")
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+ go func() {
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+ time.Sleep(time.Millisecond * 50) //give some response time
- time.Sleep(time.Millisecond * 50) //give some response time
+ respOmciLayer := &omci.OMCI{
+ TransactionID: tid,
+ MessageType: omci.ActivateSoftwareResponseType,
+ // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
+ // Length: 0x28, // Optional, defaults to 40 octets
+ }
+ response := &omci.ActivateSoftwareResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.SoftwareImageClassID,
+ EntityInstance: aImageMeID, //inactive image
+ },
+ Result: 0, //simulate done, option would be busy
+ }
+ var respOptions gopacket.SerializeOptions
+ respOptions.FixLengths = true
+ respBuffer := gopacket.NewSerializeBuffer()
+ respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+ if respErr != nil {
+ logger.Errorw(ctx, "Cannot serialize ActivateSwResponse", log.Fields{"Err": respErr,
+ "device-id": oo.deviceID})
+ return
+ }
+ respPacket := respBuffer.Bytes()
+ logger.Debugw(ctx, "simulate ActivateSwResponse", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16),
+ "result": 0})
+ go func(oo *omciCC) {
+ _ = oo.receiveMessage(ctx, respPacket)
+ }(oo)
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ }()
+ return nil
+}
- respOmciLayer := &omci.OMCI{
+func (oo *omciCC) sendCommitSoftware(ctx context.Context, timeout int, highPrio bool,
+ rxChan chan Message, aImageMeID uint16) error {
+ tid := oo.getNextTid(highPrio)
+ logger.Debugw(ctx, "send CommitSwRequest:", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+
+ omciLayer := &omci.OMCI{
TransactionID: tid,
- MessageType: omci.ActivateSoftwareResponseType,
+ MessageType: omci.CommitSoftwareRequestType,
// DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
// Length: 0x28, // Optional, defaults to 40 octets
}
- response := &omci.ActivateSoftwareResponse{
+ request := &omci.CommitSoftwareRequest{
MeBasePacket: omci.MeBasePacket{
EntityClass: me.SoftwareImageClassID,
EntityInstance: aImageMeID, //inactive image
},
- Result: 0, //simulate done, option would be busy
}
- var respOptions gopacket.SerializeOptions
- respOptions.FixLengths = true
- respBuffer := gopacket.NewSerializeBuffer()
- respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
- if respErr != nil {
- logger.Errorw(ctx, "Cannot serialize ActivateSwResponse", log.Fields{"Err": respErr,
+
+ var options gopacket.SerializeOptions
+ options.FixLengths = true
+ buffer := gopacket.NewSerializeBuffer()
+ err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+ if err != nil {
+ logger.Errorw(ctx, "Cannot serialize CommitSwRequest", log.Fields{"Err": err,
"device-id": oo.deviceID})
- return respErr
+ return err
}
- respPacket := respBuffer.Bytes()
- logger.Debugw(ctx, "simulate ActivateSwResponse", log.Fields{"device-id": oo.deviceID,
- "SequNo": strconv.FormatInt(int64(tid), 16),
- "InstId": strconv.FormatInt(int64(aImageMeID), 16),
- "result": 0})
- go func(oo *omciCC) {
- _ = oo.receiveMessage(ctx, respPacket)
- }(oo)
- //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ outgoingPacket := buffer.Bytes()
+
+ omciRxCallbackPair := callbackPair{cbKey: tid,
+ cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
+ }
+ err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw(ctx, "Cannot send CommitSwRequest", log.Fields{"Err": err,
+ "device-id": oo.deviceID})
+ return err
+ }
+ logger.Debug(ctx, "send CommitSwRequest done")
+
+ go func() {
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+ time.Sleep(time.Millisecond * 50) //give some response time
+ respOmciLayer := &omci.OMCI{
+ TransactionID: tid,
+ MessageType: omci.CommitSoftwareResponseType,
+ // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline
+ // Length: 0x28, // Optional, defaults to 40 octets
+ }
+ response := &omci.CommitSoftwareResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.SoftwareImageClassID,
+ EntityInstance: aImageMeID, //inactive image
+ },
+ //TODO: Not yet supported by omci-lib Result: 0, //simulate done
+ }
+ var respOptions gopacket.SerializeOptions
+ respOptions.FixLengths = true
+ respBuffer := gopacket.NewSerializeBuffer()
+ respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+ if respErr != nil {
+ logger.Errorw(ctx, "Cannot serialize CommitSwResponse", log.Fields{"Err": respErr,
+ "device-id": oo.deviceID})
+ return
+ }
+ respPacket := respBuffer.Bytes()
+ logger.Debugw(ctx, "simulate CommitSwResponse", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aImageMeID), 16),
+ "result": 0})
+ go func(oo *omciCC) {
+ _ = oo.receiveMessage(ctx, respPacket)
+ }(oo)
+ //**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+ }()
return nil
}
diff --git a/internal/pkg/onuadaptercore/omci_onu_upgrade.go b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
index 7842717..618d265 100644
--- a/internal/pkg/onuadaptercore/omci_onu_upgrade.go
+++ b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
@@ -54,6 +54,7 @@
upgradeEvRequestActivate = "upgradeEvRequestActivate"
upgradeEvWaitForCommit = "upgradeEvWaitForCommit"
upgradeEvCommitSw = "upgradeEvCommitSw"
+ upgradeEvCheckCommitted = "upgradeEvCheckCommitted"
//upgradeEvTimeoutSimple = "upgradeEvTimeoutSimple"
//upgradeEvTimeoutMids = "upgradeEvTimeoutMids"
@@ -73,6 +74,7 @@
upgradeStRequestingActivate = "upgradeStRequestingActivate"
upgradeStWaitForCommit = "upgradeStWaitForCommit"
upgradeStCommitSw = "upgradeStCommitSw"
+ upgradeStCheckCommitted = "upgradeStCheckCommitted"
upgradeStResetting = "upgradeStResetting"
)
@@ -84,6 +86,7 @@
pDeviceHandler *deviceHandler
pDownloadManager *adapterDownloadManager
deviceID string
+ pOnuOmciDevice *OnuDeviceEntry
pOmciCC *omciCC
pOnuDB *onuDeviceDB
requestEvent OnuDeviceEvent
@@ -93,7 +96,8 @@
imageBuffer []byte
origImageLength uint32 //as also limited by OMCI
imageLength uint32 //including last bytes padding
- omciDownloadWindowSizeLimit uint8 //windowSize-1
+ omciDownloadWindowSizeLimit uint8 //windowSize-1 in sections
+ omciDownloadWindowSizeLast uint8 //number of sections in last window
noOfSections uint32 //uint32 range for sections should be sufficient for very long images
nextDownloadSectionsAbsolute uint32 //number of next section to download in overall image
nextDownloadSectionsWindow uint8 //number of next section to download within current window
@@ -102,17 +106,19 @@
inactiveImageMeID uint16 //ME-ID of the inactive image
omciSectionInterleaveMilliseconds time.Duration //DownloadSectionInterleave delay in milliseconds
delayEndSwDl bool //flag to provide a delay between last section and EndSwDl
+ pLastTxMeInstance *me.ManagedEntity
}
//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
// of ONU UNI ports via OMCI
func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler *deviceHandler,
- apDevOmciCC *omciCC, apOnuDB *onuDeviceDB,
+ apDevEntry *OnuDeviceEntry, apOnuDB *onuDeviceDB,
aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message) *OnuUpgradeFsm {
instFsm := &OnuUpgradeFsm{
pDeviceHandler: apDeviceHandler,
deviceID: apDeviceHandler.deviceID,
- pOmciCC: apDevOmciCC,
+ pOnuOmciDevice: apDevEntry,
+ pOmciCC: apDevEntry.PDevOmciCC,
pOnuDB: apOnuDB,
requestEvent: aRequestEvent,
omciDownloadWindowSizeLimit: cOmciDownloadWindowSizeLimit,
@@ -138,6 +144,7 @@
{Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
{Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStWaitForCommit},
Dst: upgradeStCommitSw},
+ {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
/*
{Name: upgradeEvTimeoutSimple, Src: []string{
@@ -148,11 +155,11 @@
// exceptional treatments
{Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStPreparingDL, upgradeStDLSection,
upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStRequestingActivate,
- upgradeStCommitSw}, //upgradeStWaitForCommit is not reset (later perhaps also not upgradeStWaitActivate)
+ upgradeStCommitSw, upgradeStCheckCommitted}, //upgradeStWaitForCommit is not reset (later perhaps also not upgradeStWaitActivate)
Dst: upgradeStResetting},
{Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStPreparingDL, upgradeStDLSection,
upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStRequestingActivate,
- upgradeStWaitForCommit, upgradeStCommitSw},
+ upgradeStWaitForCommit, upgradeStCommitSw, upgradeStCheckCommitted},
Dst: upgradeStResetting},
{Name: upgradeEvRestart, Src: []string{upgradeStResetting}, Dst: upgradeStDisabled},
},
@@ -165,6 +172,7 @@
"enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
"enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
"enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
+ "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
"enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
"enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
},
@@ -180,12 +188,13 @@
}
//SetDownloadParams configures the needed parameters for a specific download to the ONU
-func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, apImageDsc *voltha.ImageDownload,
- apDownloadManager *adapterDownloadManager) error {
+func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
+ apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
pBaseFsm := oFsm.pAdaptFsm.pFsm
if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
"device-id": oFsm.deviceID, "image-description": apImageDsc})
+ oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
oFsm.pImageDsc = apImageDsc
oFsm.pDownloadManager = apDownloadManager
@@ -219,7 +228,7 @@
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
return
}
@@ -232,7 +241,7 @@
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
return
}
@@ -246,7 +255,6 @@
}
oFsm.origImageLength = uint32(fileLen)
oFsm.imageLength = uint32(len(oFsm.imageBuffer))
- oFsm.inactiveImageMeID = uint16(1) //just to start with, must be detected from upload data or even determined per new request?
logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
"MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
@@ -261,7 +269,7 @@
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
return
}
@@ -296,7 +304,7 @@
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
return
}
@@ -309,23 +317,23 @@
if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
windowAckRequest = 1
framePrint = true //debug print of last frame
- logger.Debugw(ctx, "DlSection expect Response for last window (section)", log.Fields{
+ oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
+ logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
"device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
}
err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, false,
oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
if err != nil {
logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
- "device-id": oFsm.deviceID, "error": err})
+ "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
//TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
return
}
-
oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
if windowAckRequest == 1 {
pBaseFsm := oFsm.pAdaptFsm
@@ -369,7 +377,7 @@
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
return
}
@@ -388,16 +396,64 @@
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
return
}
}
func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
- logger.Infow(ctx, "OnuUpgradeFsm commit SW - not yet implemented", log.Fields{
+ if activeImageID, err := oFsm.pOnuOmciDevice.GetActiveImageMeID(ctx); err == nil {
+ //TODO!!: as long as testing with BBSIM and BBSIM not support upgrade tests following check needs to be deactivated
+ imageFit := true //TODO!!: test workaround as long as BBSIM does not fully support upgrade
+ if imageFit || activeImageID == oFsm.inactiveImageMeID {
+ logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
+ "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID}) //more efficient activeImageID with above check
+ err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, false,
+ oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID) //more efficient activeImageID with above check
+ if err != nil {
+ logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
+ "device-id": oFsm.deviceID, "error": err})
+ //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ pBaseFsm := oFsm.pAdaptFsm
+ // Can't call FSM Event directly, decoupling it
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
+ }(pBaseFsm)
+ return
+ }
+ return
+ }
+ logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
+ "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
+ //TODO!!!: possibly send event information for aborted upgrade (not activated)??
+ pBaseFsm := oFsm.pAdaptFsm
+ // Can't call FSM Event directly, decoupling it
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
+ }(pBaseFsm)
+ return
+ }
+ logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
+ "device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ pBaseFsm := oFsm.pAdaptFsm
+ // Can't call FSM Event directly, decoupling it
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
+ }(pBaseFsm)
+}
+
+func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
+ logger.Infow(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
"device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
- //here should be the sending of the software commit message and staying here while waiting for the response
+ requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
+ meInstance := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
+ me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, ConstDefaultOmciTimeout, false, oFsm.pAdaptFsm.commChan)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ oFsm.pLastTxMeInstance = meInstance
}
func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
@@ -443,7 +499,7 @@
if !ok {
logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
// but then we have to ensure a restart of the FSM as well - as exceptional procedure
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvReset)
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
break loop
}
logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
@@ -479,12 +535,16 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
@@ -493,6 +553,8 @@
logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
@@ -520,21 +582,26 @@
logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
// TODO!!!: possibly repeat the start request (once)?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
} //StartSoftwareDownloadResponseType
case omci.DownloadSectionResponseType:
{
- /* TODO!!!: Have to remove the check here as current used omci-lib does not allow msg layering here
msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
@@ -542,35 +609,46 @@
if msgObj.Result != me.Success {
logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
sectionNumber := msgObj.SectionNumber
- */
- sectionNumber := oFsm.omciDownloadWindowSizeLimit //as long as access from omci-lib is not given above!!!
- logger.Debugw(ctx, "DlSectionResponse received", log.Fields{
- "window section-number": sectionNumber, "device-id": oFsm.deviceID})
- if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
- logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
- log.Fields{"device-id": oFsm.deviceID, "window-section-limit": oFsm.omciDownloadWindowSizeLimit})
- return
- }
+ logger.Infow(ctx, "DlSectionResponse received", log.Fields{
+ "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
- oFsm.nextDownloadWindow++
- if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
- oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
+ oFsm.nextDownloadWindow++
+ if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
+ if sectionNumber != oFsm.omciDownloadWindowSizeLast {
+ logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
+ log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
+ "expected section": oFsm.omciDownloadWindowSizeLast})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
+ return
+ }
+ if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
+ logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
+ log.Fields{"device-id": oFsm.deviceID, "window-section-limit": oFsm.omciDownloadWindowSizeLimit})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ oFsm.nextDownloadSectionsWindow = 0
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
return
}
- oFsm.nextDownloadSectionsWindow = 0
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
- return
- /* }
logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
- // TODO!!!: possibly repeat the start request (once)?
+ // TODO!!!: possibly repeat the download (section) (once)?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
- */
} //DownloadSectionResponseType
case omci.EndSoftwareDownloadResponseType:
{
@@ -578,12 +656,16 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
@@ -593,6 +675,8 @@
logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
@@ -603,6 +687,8 @@
logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
// TODO!!!: possibly repeat the end request (once)? or verify ONU upgrade state?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
} //EndSoftwareDownloadResponseType
case omci.ActivateSoftwareResponseType:
@@ -611,12 +697,16 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
@@ -625,18 +715,123 @@
logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
// TODO!!!: error treatment?, perhaps in the end reset the FSM
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
logger.Debugw(ctx, "Expected ActivateSwResponse received", log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
+ //TODO: as long as BBSIM does not fully support upgrade: simulate restart by calling the BBSIM (ONU) reboot
+ go oFsm.pDeviceHandler.rebootDevice(ctx, false, oFsm.pDeviceHandler.device)
return
}
logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
- // TODO!!!: error treatment?, perhaps in the end reset the FSM
+ // TODO!!!: error treatment?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
} //ActivateSoftwareResponseType
+ case omci.CommitSoftwareResponseType:
+ {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
+ log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
+ log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ // TODO!!: not yet implemented by omci-lib:
+ /*if msgObj.Result != me.Success {
+ logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
+ log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
+ // TODO!!!: error treatment?, perhaps in the end reset the FSM
+ return
+ }*/
+ if msgObj.EntityInstance == oFsm.inactiveImageMeID {
+ logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
+ //verifying committed image
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
+ return
+ }
+ logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
+ log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
+ // TODO!!!: error treatment?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ } //CommitSoftwareResponseType
+ case omci.GetResponseType:
+ {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
+ log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.GetResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
+ log.Fields{"device-id": oFsm.deviceID})
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
+ "device-id": oFsm.deviceID, "data-fields": msgObj})
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ if msgObj.Result != me.Success {
+ logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
+ log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
+ // TODO!!!: error treatment?, perhaps in the end reset the FSM
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ } else {
+ logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
+ log.Fields{"device-id": oFsm.deviceID})
+ return
+ }
+
+ meAttributes := msgObj.Attributes
+ imageIsCommitted := meAttributes["IsCommitted"].(uint8)
+ imageIsActive := meAttributes["IsActive"].(uint8)
+ imageVersion := trimStringFromInterface(meAttributes["Version"])
+ logger.Infow(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
+ log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
+ "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
+
+ //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
+ // indicated in the download image version string (version must be part of the image content itself)
+ // so checking that might be quite unreliable
+ if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive &&
+ imageIsCommitted == swIsCommitted {
+ logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
+ //releasing the upgrade FSM
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvReset)
+ return
+ }
+ logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
+ log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
+ // TODO!!!: error treatment?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ } //GetResponseType
default:
{
logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
diff --git a/internal/pkg/onuadaptercore/omci_vlan_config.go b/internal/pkg/onuadaptercore/omci_vlan_config.go
index a53b115..3a33a0f 100644
--- a/internal/pkg/onuadaptercore/omci_vlan_config.go
+++ b/internal/pkg/onuadaptercore/omci_vlan_config.go
@@ -332,8 +332,8 @@
//RequestClearPersistency sets the internal flag to not clear persistency data (false=NoClear)
func (oFsm *UniVlanConfigFsm) RequestClearPersistency(aClear bool) {
//mutex protection is required for possible concurrent access to FSM members
- oFsm.mutexFlowParams.RLock()
- defer oFsm.mutexFlowParams.RUnlock()
+ oFsm.mutexFlowParams.Lock()
+ defer oFsm.mutexFlowParams.Unlock()
oFsm.clearPersistency = aClear
}
@@ -436,7 +436,6 @@
kvStoreWrite := false //default setting is to not write to kvStore immediately - will be done on FSM execution finally
if requestAppendRule {
oFsm.mutexFlowParams.Lock()
- defer oFsm.mutexFlowParams.Unlock()
if oFsm.numUniFlows < cMaxAllowedFlows {
loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
loFlowParams.CookieSlice = make([]uint64, 0)
@@ -489,17 +488,21 @@
}
} // if not in the appropriate state a new entry will be automatically considered later
// when the configDone state is reached
+ oFsm.mutexFlowParams.Unlock()
} else {
logger.Errorw(ctx, "UniVlanConfigFsm flow limit exceeded", log.Fields{
"device-id": oFsm.deviceID, "flow-number": oFsm.numUniFlows})
+ oFsm.mutexFlowParams.Unlock()
return fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
}
} else {
// no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
+ oFsm.mutexFlowParams.RLock()
if oFsm.numUniFlows == oFsm.configuredUniFlow {
//all requested rules really have been configured
// state transition notification is checked in deviceHandler
+ oFsm.mutexFlowParams.RUnlock()
if oFsm.pDeviceHandler != nil {
//also the related TechProfile was already configured
logger.Debugw(ctx, "UniVlanConfigFsm rule already set - send immediate add-success event for reason update", log.Fields{
@@ -513,16 +516,20 @@
logger.Debugw(ctx, "UniVlanConfigFsm rule already set but configuration ongoing, suppress early add-success event for reason update",
log.Fields{"device-id": oFsm.deviceID,
"NumberofRules": oFsm.numUniFlows, "Configured rules": oFsm.configuredUniFlow})
+ oFsm.mutexFlowParams.RUnlock()
}
}
if flowCookieModify { // some change was done to the flow entries
//permanently store flow config for reconcile case
+ oFsm.mutexFlowParams.RLock()
if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
&oFsm.uniVlanFlowParamsSlice, kvStoreWrite); err != nil {
+ oFsm.mutexFlowParams.RUnlock()
logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
return err
}
+ oFsm.mutexFlowParams.RUnlock()
}
return nil
}
@@ -639,9 +646,9 @@
var loRemoveParams uniRemoveVlanFlowParams = uniRemoveVlanFlowParams{}
logger.Debugw(ctx, "UniVlanConfigFsm flow removal - full flow removal", log.Fields{
"device-id": oFsm.deviceID})
- //rwCore flow recovery may be the reson for this delete, in which case the flowToBeDeleted may be the same
+ //rwCore flow recovery may be the reason for this delete, in which case the flowToBeDeleted may be the same
// as the one still waiting in the FSM as toAdd but waiting for TechProfileConfig
- // so we have to to check that here in in this case have to abort the outstanding AddRequest and regard the current DelRequest as done
+ // so we have to check if we have to abort the outstanding AddRequest and regard the current DelRequest as done
// if the Fsm is in some other transient (config) state, we will reach the DelRequest later and correctly process it then
if pConfigVlanStateBaseFsm.Is(vlanStWaitingTechProf) {
logger.Debugw(ctx, "UniVlanConfigFsm was waiting for TechProf config with this rule, aborting the outstanding config",
@@ -990,10 +997,10 @@
}
func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(ctx context.Context, e *fsm.Event) {
+ oFsm.mutexFlowParams.Lock()
logger.Debugw(ctx, "UniVlanConfigFsm - start config further incremental flow", log.Fields{
"in state": e.FSM.Current(), "recent flow-number": oFsm.configuredUniFlow,
"device-id": oFsm.deviceID})
- oFsm.mutexFlowParams.Lock()
oFsm.TpIDWaitingFor = 0 //reset indication to avoid misinterpretation
if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
@@ -1013,7 +1020,6 @@
// 'SetVid' below is assumed to be masked already by the caller to 12 bit
oFsm.vlanFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
- oFsm.mutexFlowParams.Unlock()
vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
vtfdFilterList[0] = oFsm.vlanFilterList[0]
oFsm.numVlanFilterEntries = 1
@@ -1051,7 +1057,6 @@
// VTFD has to be created afresh with a new entity ID that has the same entity ID as the MBPCD ME for every
// new vlan associated with a different TP.
vtfdFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
- oFsm.mutexFlowParams.Unlock()
oFsm.numVlanFilterEntries++
meParams := me.ParamData{
@@ -1071,6 +1076,7 @@
// (relevant to all used sendXX() methods in this (and other) FSM's)
oFsm.pLastTxMeInstance = meInstance
}
+ oFsm.mutexFlowParams.Unlock()
//verify response
err := oFsm.waitforOmciResponse(ctx)
if err != nil {
@@ -1084,18 +1090,25 @@
return
}
}
+ oFsm.mutexFlowParams.Lock()
oFsm.requestEventOffset = uint8(cDeviceEventOffsetAddWithKvStore) //0 offset for last flow-add activity
+ oFsm.mutexFlowParams.Unlock()
go func() {
+ oFsm.mutexFlowParams.RLock()
tpID := oFsm.actualUniVlanConfigRule.TpID
- errEvto := oFsm.performConfigEvtocdEntries(ctx, oFsm.configuredUniFlow)
+ configuredUniFlow := oFsm.configuredUniFlow
+ oFsm.mutexFlowParams.RUnlock()
+ errEvto := oFsm.performConfigEvtocdEntries(ctx, configuredUniFlow)
//This is correct passing scenario
if errEvto == nil {
//TODO Possibly insert new state for multicast --> possibly another jira/later time.
for _, gemPort := range oFsm.pUniTechProf.getMulticastGemPorts(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID)) {
+ oFsm.mutexFlowParams.RLock()
vlanID := oFsm.actualUniVlanConfigRule.SetVid
logger.Infow(ctx, "Setting multicast MEs for additional flows", log.Fields{"deviceID": oFsm.deviceID,
"techProfile": tpID, "gemPort": gemPort,
"vlanID": vlanID, "configuredUniFlow": oFsm.configuredUniFlow})
+ oFsm.mutexFlowParams.RUnlock()
errCreateAllMulticastME := oFsm.performSettingMulticastME(ctx, tpID, gemPort, vlanID)
if errCreateAllMulticastME != nil {
logger.Errorw(ctx, "Multicast ME create failed, aborting AniConfig FSM!",
@@ -1206,6 +1219,7 @@
}
}
+ oFsm.mutexFlowParams.Lock()
if loVlanEntryClear == 1 {
oFsm.vlanFilterList[0] = 0 //first entry is the only that can contain the previous only-one element
oFsm.numVlanFilterEntries = 0
@@ -1217,6 +1231,7 @@
}
oFsm.numVlanFilterEntries--
}
+ oFsm.mutexFlowParams.Unlock()
}
}
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index 301a973..25ffaa3 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -199,6 +199,14 @@
firstSwImageMeID = 0
secondSwImageMeID = 1
)
+const ( //definitions as per G.988 softwareImage::IsCommitted
+ swIsUncommitted = 0
+ swIsCommitted = 1
+)
+const ( //definitions as per G.988 softwareImage::IsActive
+ //swIsInactive = 0 not yet used
+ swIsActive = 1
+)
const onuDataMeID = 0
const onugMeID = 0
const onu2gMeID = 0
@@ -209,9 +217,15 @@
const cEmptyMacAddrString = "000000000000"
const cEmptySerialNumberString = "0000000000000000"
-type swImages struct {
- version string
- isActive uint8
+type sEntrySwImageIndication struct {
+ valid bool
+ entityID uint16
+ version string
+ isCommitted uint8
+}
+type sSwImageIndications struct {
+ activeEntityEntry sEntrySwImageIndication
+ inactiveEntityEntry sEntrySwImageIndication
}
type uniPersConfig struct {
@@ -255,7 +269,7 @@
vendorID string
serialNumber string
equipmentID string
- swImages [secondSwImageMeID + 1]swImages
+ onuSwImageIndications sSwImageIndications
activeSwVersion string
macAddress string
//lockDeviceEntries sync.RWMutex
@@ -448,7 +462,7 @@
)
if onuDeviceEntry.pMibDownloadFsm == nil || onuDeviceEntry.pMibDownloadFsm.pFsm == nil {
logger.Errorw(ctx, "MibDownloadFsm could not be instantiated", log.Fields{"device-id": dh.deviceID})
- // TODO some specifc error treatment - or waiting for crash ?
+ // TODO some specific error treatment - or waiting for crash ?
}
onuDeviceEntry.mibTemplateKVStore = onuDeviceEntry.baseDeviceHandler.setBackend(ctx, cBasePathMibTemplateKvStore)
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index e129c6f..357219b 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -362,7 +362,7 @@
func (oo *OpenONUAC) Reboot_device(ctx context.Context, device *voltha.Device) error {
logger.Infow(ctx, "reboot-device", log.Fields{"device-id": device.Id})
if handler := oo.getDeviceHandler(ctx, device.Id, false); handler != nil {
- go handler.rebootDevice(ctx, device)
+ go handler.rebootDevice(ctx, true, device) //reboot request with device checking
return nil
}
logger.Warnw(ctx, "no handler found for device-reboot", log.Fields{"device-id": device.Id})
@@ -455,16 +455,19 @@
//Download_image requests downloading some image according to indications as given in request
//The ImageDownload needs to be called `request`due to library reflection requirements
func (oo *OpenONUAC) Download_image(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
- if !oo.pDownloadManager.imageExists(ctx, request) {
- logger.Debugw(ctx, "start image download", log.Fields{"image-description": request})
- // Download_image is not supposed to be blocking, anyway let's call the DownloadManager still synchronously to detect 'fast' problems
- // the download itself is later done in background
- err := oo.pDownloadManager.startDownload(ctx, request)
- return request, err
+ if request != nil && (*request).Name != "" {
+ if !oo.pDownloadManager.imageExists(ctx, request) {
+ logger.Debugw(ctx, "start image download", log.Fields{"image-description": request})
+ // Download_image is not supposed to be blocking, anyway let's call the DownloadManager still synchronously to detect 'fast' problems
+ // the download itself is later done in background
+ err := oo.pDownloadManager.startDownload(ctx, request)
+ return request, err
+ }
+ // image already exists
+ logger.Debugw(ctx, "image already downloaded", log.Fields{"image-description": request})
+ return request, nil
}
- // image already exists
- logger.Debugw(ctx, "image already downloaded", log.Fields{"image-description": request})
- return request, nil
+ return request, errors.New("invalid image definition")
}
//Get_image_download_status unimplemented
@@ -483,18 +486,21 @@
// according to indications as given in request and on success activate the image on the ONU
//The ImageDownload needs to be called `request`due to library reflection requirements
func (oo *OpenONUAC) Activate_image_update(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
- if oo.pDownloadManager.imageLocallyDownloaded(ctx, request) {
- if handler := oo.getDeviceHandler(ctx, device.Id, false); handler != nil {
- logger.Debugw(ctx, "image download on omci requested", log.Fields{
- "image-description": request, "device-id": device.Id})
- err := handler.doOnuSwUpgrade(ctx, request, oo.pDownloadManager)
- return request, err
+ if request != nil && (*request).Name != "" {
+ if oo.pDownloadManager.imageLocallyDownloaded(ctx, request) {
+ if handler := oo.getDeviceHandler(ctx, device.Id, false); handler != nil {
+ logger.Debugw(ctx, "image download on omci requested", log.Fields{
+ "image-description": request, "device-id": device.Id})
+ err := handler.doOnuSwUpgrade(ctx, request, oo.pDownloadManager)
+ return request, err
+ }
+ logger.Warnw(ctx, "no handler found for image activation", log.Fields{"device-id": device.Id})
+ return request, fmt.Errorf(fmt.Sprintf("handler-not-found - device-id: %s", device.Id))
}
- logger.Warnw(ctx, "no handler found for image activation", log.Fields{"device-id": device.Id})
- return request, fmt.Errorf(fmt.Sprintf("handler-not-found - device-id: %s", device.Id))
+ logger.Debugw(ctx, "image not yet downloaded on activate request", log.Fields{"image-description": request})
+ return request, fmt.Errorf(fmt.Sprintf("image-not-yet-downloaded - device-id: %s", device.Id))
}
- logger.Debugw(ctx, "image not yet downloaded on activate request", log.Fields{"image-description": request})
- return request, fmt.Errorf(fmt.Sprintf("image-not-yet-downloaded - device-id: %s", device.Id))
+ return request, errors.New("invalid image definition")
}
//Revert_image_update unimplemented
diff --git a/vendor/github.com/opencord/omci-lib-go/VERSION b/vendor/github.com/opencord/omci-lib-go/VERSION
index 4312e0d..9f40a87 100644
--- a/vendor/github.com/opencord/omci-lib-go/VERSION
+++ b/vendor/github.com/opencord/omci-lib-go/VERSION
@@ -1 +1 @@
-0.15.2
+0.15.4
\ No newline at end of file
diff --git a/vendor/github.com/opencord/omci-lib-go/messagetypes.go b/vendor/github.com/opencord/omci-lib-go/messagetypes.go
index c237e72..6776b06 100644
--- a/vendor/github.com/opencord/omci-lib-go/messagetypes.go
+++ b/vendor/github.com/opencord/omci-lib-go/messagetypes.go
@@ -2285,13 +2285,13 @@
if err != nil {
return err
}
- bytes[0] = omci.SectionNumber
if omci.Result > me.DeviceBusy {
msg := fmt.Sprintf("invalid results for Download Section response: %v, must be 0..6",
omci.Result)
return errors.New(msg)
}
- bytes[1] = byte(omci.Result)
+ bytes[0] = byte(omci.Result)
+ bytes[1] = omci.SectionNumber
return nil
}
@@ -2332,7 +2332,7 @@
}
omci.CRC32 = binary.BigEndian.Uint32(data[4:8])
omci.ImageSize = binary.BigEndian.Uint32(data[8:12])
- omci.NumberOfInstances = data[13]
+ omci.NumberOfInstances = data[12]
if omci.NumberOfInstances < 1 || omci.NumberOfInstances > 9 {
return me.NewProcessingError(fmt.Sprintf("invalid number of Instances: %v, must be 1..9",
@@ -2341,7 +2341,7 @@
omci.ImageInstances = make([]uint16, omci.NumberOfInstances)
for index := 0; index < int(omci.NumberOfInstances); index++ {
- omci.ImageInstances[index] = binary.BigEndian.Uint16(data[14+(index*2):])
+ omci.ImageInstances[index] = binary.BigEndian.Uint16(data[13+(index*2):])
}
return nil
}
@@ -2380,11 +2380,11 @@
if err != nil {
return err
}
- binary.BigEndian.PutUint32(bytes[4:8], omci.CRC32)
- binary.BigEndian.PutUint32(bytes[8:12], omci.ImageSize)
- bytes[13] = omci.NumberOfInstances
+ binary.BigEndian.PutUint32(bytes[0:4], omci.CRC32)
+ binary.BigEndian.PutUint32(bytes[4:8], omci.ImageSize)
+ bytes[8] = omci.NumberOfInstances
for index := 0; index < int(omci.NumberOfInstances); index++ {
- binary.BigEndian.PutUint16(bytes[14+(index*2):], omci.ImageInstances[index])
+ binary.BigEndian.PutUint16(bytes[9+(index*2):], omci.ImageInstances[index])
}
return nil
}
@@ -2478,7 +2478,7 @@
if omci.EntityClass != me.SoftwareImageClassID {
return me.NewProcessingError("invalid Entity Class for End Download response")
}
- bytes, err := b.AppendBytes(3 + (3 * int(omci.NumberOfInstances)))
+ bytes, err := b.AppendBytes(2 + (3 * int(omci.NumberOfInstances)))
if err != nil {
return err
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 4da7c41..0ebb307 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -55,7 +55,7 @@
github.com/jcmturner/gofork/x/crypto/pbkdf2
# github.com/looplab/fsm v0.1.0
github.com/looplab/fsm
-# github.com/opencord/omci-lib-go v0.15.2
+# github.com/opencord/omci-lib-go v0.15.4
github.com/opencord/omci-lib-go
github.com/opencord/omci-lib-go/generated
# github.com/opencord/voltha-lib-go/v4 v4.0.10