[VOL-4472] BBSim receives two "EndSoftwareDownloadRequest" when you abort the download
Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: Id213af2e68c6a8f381d398f8be00b6d8b0a67b8e
diff --git a/VERSION b/VERSION
index 5fca835..1111a33 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.2-dev254
+2.1.2-dev256
diff --git a/internal/pkg/swupg/omci_onu_upgrade.go b/internal/pkg/swupg/omci_onu_upgrade.go
index fe4aac2..c0660b8 100755
--- a/internal/pkg/swupg/omci_onu_upgrade.go
+++ b/internal/pkg/swupg/omci_onu_upgrade.go
@@ -173,6 +173,7 @@
imageIdentifier string //name of the image as used in the adapter
mutexIsAwaitingAdapterDlResponse sync.RWMutex
chAdapterDlReady chan bool
+ chAbortDelayEndSwDl chan struct{}
isWaitingForAdapterDlResponse bool
chOnuDlReady chan bool
activateImage bool
@@ -214,6 +215,7 @@
}
instFsm.chReceiveExpectedResponse = make(chan bool)
instFsm.chAdapterDlReady = make(chan bool)
+ instFsm.chAbortDelayEndSwDl = make(chan struct{})
instFsm.chOnuDlReady = make(chan bool)
instFsm.chReceiveAbortEndSwDlResponse = make(chan tEndSwDlResponseResult)
@@ -550,6 +552,14 @@
} else {
oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
}
+
+ //abort a possible delaying of sending EndSwDl
+ //use asynchronous channel sending to avoid blocking here in case no receiver is waiting
+ select {
+ case oFsm.chAbortDelayEndSwDl <- struct{}{}:
+ default:
+ }
+
//chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
// in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
@@ -703,7 +713,7 @@
logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
"device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
//use a background routine to send the multiple download sections frames in a loop
- // in order to avoid blocking on synchrounous event calls for the entire (long) processing time
+ // in order to avoid blocking on synchronous event calls for the entire (long) processing time
go oFsm.runSwDlSectionWindow(ctx)
}
@@ -816,13 +826,30 @@
func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
"device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
+ //use a background routine to wait EndSwDlDelay and then send the EndSwDl request
+ // in order to avoid blocking on synchronous event calls for the complete wait time
+ // and to allow for state transition before sending the EndSwDl request
+ go oFsm.delayAndSendEndSwDl(ctx)
+}
+//delayAndSendEndSwDl ensures a delay before sending the EndSwDl request
+// may also be aborted by parallel channel reception on chAbortEndSwDl
+func (oFsm *OnuUpgradeFsm) delayAndSendEndSwDl(ctx context.Context) {
oFsm.mutexUpgradeParams.RLock()
if oFsm.delayEndSwDl {
oFsm.mutexUpgradeParams.RUnlock()
- //give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
- // should not be set in case this state is used for real download abort (not yet implemented)
- time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
+ //give the ONU some time for image evaluation (hoping it does not only start this evaluation on first EndSwDl itself)
+ logger.Debugw(ctx, "OnuUpgradeFsm delay EndSwDl", log.Fields{"device-id": oFsm.deviceID,
+ "duration_s": cOmciEndSwDlDelaySeconds})
+ select {
+ case <-time.After(cOmciEndSwDlDelaySeconds * time.Second):
+ logger.Warnw(ctx, "OnuUpgradeFsm start sending EndSwDl", log.Fields{
+ "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier})
+ case <-oFsm.chAbortDelayEndSwDl:
+ logger.Debugw(ctx, "OnuUpgradeFsm abort request to send EndSwDl", log.Fields{"device-id": oFsm.deviceID})
+ //according further state transition is ensured by the entity that sent the abort
+ return
+ }
} else {
oFsm.mutexUpgradeParams.RUnlock()
}
@@ -834,9 +861,7 @@
oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
oFsm.mutexUpgradeParams.Unlock()
// Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *cmn.AdapterFsm) {
- _ = a_pAFsm.PFsm.Event(UpgradeEvAbort)
- }(pBaseFsm)
+ _ = pBaseFsm.PFsm.Event(UpgradeEvAbort)
return
}
err := oFsm.pOmciCC.SendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.GetOmciTimeout(), false,
@@ -848,12 +873,13 @@
oFsm.abortOnOmciError(ctx, true)
return
}
- // go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
- // Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *cmn.AdapterFsm) {
- _ = a_pAFsm.PFsm.Event(UpgradeEvWaitEndDownload)
- }(pBaseFsm)
-}
+ //from here on sending of EndSwDl(Abort) is not needed anymore (even though response is not yet received)
+ // this avoids sending of both EndSwDl(Success) and EndSwDl(Abort) when cancellation falls just into this window
+ // the ONU must theoretically be prepared to receive none of them (in case of OMCI transfer issues) e.g. by timeout
+ oFsm.isEndSwDlOpen = false
+ // wait for the EndSwDLResponse and check, if the ONU is ready for activation
+ _ = pBaseFsm.PFsm.Event(UpgradeEvWaitEndDownload)
+} //delayAndSendEndSwDl
func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
@@ -868,7 +894,6 @@
return
}
oFsm.mutexUpgradeParams.Lock()
- oFsm.isEndSwDlOpen = false //no need to additionally request abort of download (already finished)
oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
oFsm.mutexUpgradeParams.Unlock()
go func(a_pAFsm *cmn.AdapterFsm) {