blob: e687f48f56babe7eab7bba6f93e75623130df75a [file] [log] [blame]
mpagenko80622a52021-02-09 16:53:23 +00001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
mpagenkoc26d4c02021-05-06 14:27:57 +000022 "encoding/binary"
mpagenko80622a52021-02-09 16:53:23 +000023 "fmt"
24 "strconv"
mpagenkoc26d4c02021-05-06 14:27:57 +000025 "sync"
mpagenko80622a52021-02-09 16:53:23 +000026 "time"
27
28 "github.com/boguslaw-wojcik/crc32a"
29 "github.com/looplab/fsm"
30 "github.com/opencord/omci-lib-go"
31 me "github.com/opencord/omci-lib-go/generated"
Girish Gowdra50e56422021-06-01 16:46:04 -070032 "github.com/opencord/voltha-lib-go/v5/pkg/log"
mpagenko80622a52021-02-09 16:53:23 +000033 "github.com/opencord/voltha-protos/v4/go/voltha"
34)
35
36const cMaxUint32 = ^uint32(0)
37
38const (
39 // internal predefined values - some off them should later be configurable (perhaps with theses as defaults)
40 cOmciDownloadSectionSize = 31 //in bytes
41 cOmciDownloadWindowSizeLimit = 31 //in sections for window offset (windowSize(32)-1)
42 //cOmciDownloadWindowRetryMax = 2 // max attempts for a specific window
mpagenkoc26d4c02021-05-06 14:27:57 +000043 cOmciSectionInterleaveMilliseconds = 0 //DownloadSection interleave time in milliseconds (0 for no delay)
44 cOmciEndSwDlDelaySeconds = 1 //End Software Download delay after last section (may be also configurable?)
45 cWaitCountEndSwDl = 6 //maximum number of EndSwDl requests
46 cWaitDelayEndSwDlSeconds = 10 //duration, how long is waited before next request on EndSwDl
mpagenko80622a52021-02-09 16:53:23 +000047 //cOmciDownloadCompleteTimeout = 5400 //in s for the complete timeout (may be better scale to image size/ noOfWindows)
48)
49
50const (
51 // events of config PON ANI port FSM
52 upgradeEvStart = "upgradeEvStart"
mpagenkoc26d4c02021-05-06 14:27:57 +000053 upgradeEvAdapterDownload = "upgradeEvAdapterDownload"
mpagenko80622a52021-02-09 16:53:23 +000054 upgradeEvPrepareSwDownload = "upgradeEvPrepareSwDownload"
55 upgradeEvRxStartSwDownload = "upgradeEvRxStartSwDownload"
56 upgradeEvWaitWindowAck = "upgradeEvWaitWindowAck"
57 upgradeEvContinueNextWindow = "upgradeEvContinueNextWindow"
58 upgradeEvEndSwDownload = "upgradeEvEndSwDownload"
mpagenko59498c12021-03-18 14:15:15 +000059 upgradeEvWaitEndDownload = "upgradeEvWaitEndDownload"
60 upgradeEvContinueFinalize = "upgradeEvContinueFinalize"
mpagenko38662d02021-08-11 09:45:19 +000061 upgradeEvCheckImageName = "upgradeEvCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +000062 upgradeEvWaitForActivate = "upgradeEvWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000063 upgradeEvRequestActivate = "upgradeEvRequestActivate"
mpagenko183647c2021-06-08 15:25:04 +000064 upgradeEvActivationDone = "upgradeEvActivationDone"
mpagenko80622a52021-02-09 16:53:23 +000065 upgradeEvWaitForCommit = "upgradeEvWaitForCommit"
66 upgradeEvCommitSw = "upgradeEvCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +000067 upgradeEvCheckCommitted = "upgradeEvCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +000068
69 //upgradeEvTimeoutSimple = "upgradeEvTimeoutSimple"
70 //upgradeEvTimeoutMids = "upgradeEvTimeoutMids"
71 upgradeEvReset = "upgradeEvReset"
72 upgradeEvAbort = "upgradeEvAbort"
73 upgradeEvRestart = "upgradeEvRestart"
74)
75
76const (
77 // states of config PON ANI port FSM
78 upgradeStDisabled = "upgradeStDisabled"
79 upgradeStStarting = "upgradeStStarting"
mpagenkoc26d4c02021-05-06 14:27:57 +000080 upgradeStWaitingAdapterDL = "upgradeStWaitingAdapterDL"
mpagenko80622a52021-02-09 16:53:23 +000081 upgradeStPreparingDL = "upgradeStPreparingDL"
82 upgradeStDLSection = "upgradeStDLSection"
83 upgradeStVerifyWindow = "upgradeStVerifyWindow"
84 upgradeStFinalizeDL = "upgradeStFinalizeDL"
mpagenko59498c12021-03-18 14:15:15 +000085 upgradeStWaitEndDL = "upgradeStWaitEndDL"
mpagenko38662d02021-08-11 09:45:19 +000086 upgradeStCheckImageName = "upgradeStCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +000087 upgradeStWaitForActivate = "upgradeStWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000088 upgradeStRequestingActivate = "upgradeStRequestingActivate"
mpagenko183647c2021-06-08 15:25:04 +000089 upgradeStActivated = "upgradeStActivated"
mpagenko80622a52021-02-09 16:53:23 +000090 upgradeStWaitForCommit = "upgradeStWaitForCommit"
91 upgradeStCommitSw = "upgradeStCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +000092 upgradeStCheckCommitted = "upgradeStCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +000093 upgradeStResetting = "upgradeStResetting"
94)
95
96//required definition for IdleState detection for activities on OMCI
97const cOnuUpgradeFsmIdleState = upgradeStWaitForCommit
98
99//OnuUpgradeFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
100type OnuUpgradeFsm struct {
101 pDeviceHandler *deviceHandler
102 pDownloadManager *adapterDownloadManager
mpagenkoc26d4c02021-05-06 14:27:57 +0000103 pFileManager *fileDownloadManager //used from R2.8 with new API version
mpagenko80622a52021-02-09 16:53:23 +0000104 deviceID string
mpagenko38662d02021-08-11 09:45:19 +0000105 pDevEntry *OnuDeviceEntry
mpagenko80622a52021-02-09 16:53:23 +0000106 pOmciCC *omciCC
107 pOnuDB *onuDeviceDB
108 requestEvent OnuDeviceEvent
109 //omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
mpagenkoc26d4c02021-05-06 14:27:57 +0000110 pAdaptFsm *AdapterFsm
111 pImageDsc *voltha.ImageDownload
112 imageBuffer []byte
113 origImageLength uint32 //as also limited by OMCI
114 imageCRC uint32 //as per OMCI - ITU I.363.5 crc
115 imageLength uint32 //including last bytes padding
116 omciDownloadWindowSizeLimit uint8 //windowSize-1 in sections
117 omciDownloadWindowSizeLast uint8 //number of sections in last window
118 noOfSections uint32 //uint32 range for sections should be sufficient for very long images
119 nextDownloadSectionsAbsolute uint32 //number of next section to download in overall image
120 nextDownloadSectionsWindow uint8 //number of next section to download within current window
121 noOfWindows uint32 //uint32 range for windows should be sufficient for very long images
122 nextDownloadWindow uint32 //number of next window to download
123 inactiveImageMeID uint16 //ME-ID of the inactive image
124 downloadToOnuTimeout4MB time.Duration //timeout for downloading the image to the ONU for a 4MB image slice
125 omciSectionInterleaveDelay time.Duration //DownloadSectionInterleave delay in milliseconds
126 delayEndSwDl bool //flag to provide a delay between last section and EndSwDl
127 pLastTxMeInstance *me.ManagedEntity
128 waitCountEndSwDl uint8 //number, how often is waited for EndSwDl at maximum
129 waitDelayEndSwDl time.Duration //duration, how long is waited before next request on EndSwDl
130 chReceiveExpectedResponse chan bool
mpagenkoaa3afe92021-05-21 16:20:58 +0000131 useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
132 mutexUpgradeParams sync.RWMutex //mutex to protect members for parallel function requests and omci response processing
133 imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
134 imageIdentifier string //name of the image as used in the adapter
mpagenkoc26d4c02021-05-06 14:27:57 +0000135 mutexIsAwaitingAdapterDlResponse sync.RWMutex
136 chAdapterDlReady chan bool
137 isWaitingForAdapterDlResponse bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000138 chOnuDlReady chan bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000139 activateImage bool
140 commitImage bool
mpagenko38662d02021-08-11 09:45:19 +0000141 mutexAbortRequest sync.RWMutex
142 abortRequested voltha.ImageState_ImageFailureReason
143 conditionalCancelRequested bool
mpagenkoaa3afe92021-05-21 16:20:58 +0000144 volthaDownloadState voltha.ImageState_ImageDownloadState
145 volthaDownloadReason voltha.ImageState_ImageFailureReason
146 volthaImageState voltha.ImageState_ImageActivationState
mpagenko80622a52021-02-09 16:53:23 +0000147}
148
149//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
150// of ONU UNI ports via OMCI
151func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler *deviceHandler,
mpagenko15ff4a52021-03-02 10:09:20 +0000152 apDevEntry *OnuDeviceEntry, apOnuDB *onuDeviceDB,
mpagenko80622a52021-02-09 16:53:23 +0000153 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message) *OnuUpgradeFsm {
154 instFsm := &OnuUpgradeFsm{
mpagenko59498c12021-03-18 14:15:15 +0000155 pDeviceHandler: apDeviceHandler,
156 deviceID: apDeviceHandler.deviceID,
mpagenko38662d02021-08-11 09:45:19 +0000157 pDevEntry: apDevEntry,
mpagenko59498c12021-03-18 14:15:15 +0000158 pOmciCC: apDevEntry.PDevOmciCC,
159 pOnuDB: apOnuDB,
160 requestEvent: aRequestEvent,
161 omciDownloadWindowSizeLimit: cOmciDownloadWindowSizeLimit,
162 omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000163 downloadToOnuTimeout4MB: apDeviceHandler.pOpenOnuAc.dlToOnuTimeout4M,
mpagenko59498c12021-03-18 14:15:15 +0000164 waitCountEndSwDl: cWaitCountEndSwDl,
165 waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
mpagenkoaa3afe92021-05-21 16:20:58 +0000166 volthaDownloadState: voltha.ImageState_DOWNLOAD_STARTED, //if FSM created we can assume that the download (to adapter) really started
167 volthaDownloadReason: voltha.ImageState_NO_ERROR,
168 volthaImageState: voltha.ImageState_IMAGE_UNKNOWN,
mpagenko38662d02021-08-11 09:45:19 +0000169 abortRequested: voltha.ImageState_NO_ERROR,
mpagenko80622a52021-02-09 16:53:23 +0000170 }
mpagenko59498c12021-03-18 14:15:15 +0000171 instFsm.chReceiveExpectedResponse = make(chan bool)
mpagenkoc26d4c02021-05-06 14:27:57 +0000172 instFsm.chAdapterDlReady = make(chan bool)
173 instFsm.chOnuDlReady = make(chan bool)
mpagenko80622a52021-02-09 16:53:23 +0000174
175 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
176 if instFsm.pAdaptFsm == nil {
177 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
178 "device-id": instFsm.deviceID})
179 return nil
180 }
181 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
182 upgradeStDisabled,
183 fsm.Events{
184 {Name: upgradeEvStart, Src: []string{upgradeStDisabled}, Dst: upgradeStStarting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000185 {Name: upgradeEvAdapterDownload, Src: []string{upgradeStStarting}, Dst: upgradeStWaitingAdapterDL},
186 {Name: upgradeEvPrepareSwDownload, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL}, Dst: upgradeStPreparingDL},
mpagenko80622a52021-02-09 16:53:23 +0000187 {Name: upgradeEvRxStartSwDownload, Src: []string{upgradeStPreparingDL}, Dst: upgradeStDLSection},
188 {Name: upgradeEvWaitWindowAck, Src: []string{upgradeStDLSection}, Dst: upgradeStVerifyWindow},
189 {Name: upgradeEvContinueNextWindow, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStDLSection},
190 {Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
mpagenko59498c12021-03-18 14:15:15 +0000191 {Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
192 {Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
mpagenko38662d02021-08-11 09:45:19 +0000193 //upgradeStCheckImageName only used with useAPIVersion43
194 {Name: upgradeEvCheckImageName, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStCheckImageName},
195 //upgradeEvWaitForActivate state transitions depend on useAPIVersion43
196 {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL, upgradeStCheckImageName}, Dst: upgradeStWaitForActivate},
197 //upgradeEvRequestActivate state transitions depend on useAPIVersion43
198 {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStCheckImageName,
199 upgradeStWaitForActivate}, Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
mpagenko183647c2021-06-08 15:25:04 +0000200 {Name: upgradeEvActivationDone, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStActivated},
mpagenko80622a52021-02-09 16:53:23 +0000201 {Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
mpagenko1f8e8822021-06-25 14:10:21 +0000202 {Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
203 upgradeStActivated}, Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
mpagenko15ff4a52021-03-02 10:09:20 +0000204 {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000205
206 /*
207 {Name: upgradeEvTimeoutSimple, Src: []string{
208 upgradeStCreatingDot1PMapper, upgradeStCreatingMBPCD, upgradeStSettingTconts, upgradeStSettingDot1PMapper}, Dst: upgradeStStarting},
209 {Name: upgradeEvTimeoutMids, Src: []string{
210 upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
211 */
212 // exceptional treatments
mpagenko1f8e8822021-06-25 14:10:21 +0000213 //on upgradeEvReset: upgradeStRequestingActivate, upgradeStWaitForCommit and upgradeStActivated are not reset
214 // (to let the FSM survive the expected OnuDown indication)
mpagenkoc26d4c02021-05-06 14:27:57 +0000215 {Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko38662d02021-08-11 09:45:19 +0000216 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
217 upgradeStWaitForActivate,
mpagenko1f8e8822021-06-25 14:10:21 +0000218 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000219 Dst: upgradeStResetting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000220 {Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko38662d02021-08-11 09:45:19 +0000221 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
222 upgradeStWaitForActivate,
223 upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit,
224 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000225 Dst: upgradeStResetting},
226 {Name: upgradeEvRestart, Src: []string{upgradeStResetting}, Dst: upgradeStDisabled},
227 },
228 fsm.Callbacks{
229 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
230 "enter_" + upgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
mpagenkoc26d4c02021-05-06 14:27:57 +0000231 "enter_" + upgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000232 "enter_" + upgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
233 "enter_" + upgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
234 "enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
235 "enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
mpagenko59498c12021-03-18 14:15:15 +0000236 "enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
mpagenko38662d02021-08-11 09:45:19 +0000237 "enter_" + upgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000238 "enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
239 "enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
mpagenko15ff4a52021-03-02 10:09:20 +0000240 "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000241 "enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
242 "enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
243 },
244 )
245 if instFsm.pAdaptFsm.pFsm == nil {
246 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
247 "device-id": instFsm.deviceID})
248 return nil
249 }
250
251 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
252 return instFsm
253}
254
255//SetDownloadParams configures the needed parameters for a specific download to the ONU
mpagenkoc26d4c02021-05-06 14:27:57 +0000256// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000257func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
258 apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
mpagenko80622a52021-02-09 16:53:23 +0000259 pBaseFsm := oFsm.pAdaptFsm.pFsm
260 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000261 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000262 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
263 "device-id": oFsm.deviceID, "image-description": apImageDsc})
mpagenko15ff4a52021-03-02 10:09:20 +0000264 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000265 oFsm.pImageDsc = apImageDsc
266 oFsm.pDownloadManager = apDownloadManager
Holger Hildebrandtac1e0592021-06-03 15:16:49 +0000267 oFsm.activateImage = true
268 oFsm.commitImage = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000269 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000270
271 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000272 // let the upgrade FSM proceed to PreparingDL
mpagenko80622a52021-02-09 16:53:23 +0000273 _ = aPBaseFsm.Event(upgradeEvPrepareSwDownload)
274 }(pBaseFsm)
275 return nil
276 }
277 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
278 "device-id": oFsm.deviceID})
279 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
280}
281
mpagenkoc26d4c02021-05-06 14:27:57 +0000282//SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
283// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
284// called from 'new' API Download_onu_image
285func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
286 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *fileDownloadManager,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000287 aImageIdentifier string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000288 oFsm.mutexUpgradeParams.Lock()
289 var pBaseFsm *fsm.FSM = nil
290 if oFsm.pAdaptFsm != nil {
291 pBaseFsm = oFsm.pAdaptFsm.pFsm
292 }
293 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
294 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
295 "device-id": oFsm.deviceID, "image-description": apImageRequest})
296 oFsm.useAPIVersion43 = true
297 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
298 oFsm.pFileManager = apDownloadManager
299 oFsm.imageIdentifier = aImageIdentifier
300 oFsm.imageVersion = apImageRequest.Image.Version
301 oFsm.activateImage = apImageRequest.ActivateOnSuccess
302 oFsm.commitImage = apImageRequest.CommitOnSuccess
mpagenkoc26d4c02021-05-06 14:27:57 +0000303 //TODO: currently straightforward options activate and commit are expected to be set and (unconditionally) done
304 // for separate handling of these options the FSM must accordingly branch from the concerned states - later
305 oFsm.mutexUpgradeParams.Unlock()
306 _ = pBaseFsm.Event(upgradeEvAdapterDownload) //no need to call the FSM event in background here
307 return nil
308 }
309 oFsm.mutexUpgradeParams.Unlock()
310 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
311 "device-id": oFsm.deviceID})
312 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
313}
314
315//SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
316// called from 'new' API Activate_onu_image
317func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
318 aImageIdentifier string, aCommit bool) error {
319 oFsm.mutexUpgradeParams.Lock()
320 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
321 // (as long as the Imageidentifier is correct)
322 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
323 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
324 if aImageIdentifier != oFsm.imageIdentifier {
325 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
326 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
327 oFsm.mutexUpgradeParams.Unlock()
328 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
329 oFsm.deviceID))
330 }
331 oFsm.activateImage = true
332 oFsm.commitImage = aCommit
mpagenkoc26d4c02021-05-06 14:27:57 +0000333 var pBaseFsm *fsm.FSM = nil
334 if oFsm.pAdaptFsm != nil {
335 pBaseFsm = oFsm.pAdaptFsm.pFsm
336 }
337 if pBaseFsm != nil {
338 if pBaseFsm.Is(upgradeStWaitForActivate) {
mpagenko38662d02021-08-11 09:45:19 +0000339 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
340 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000341 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
342 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenko38662d02021-08-11 09:45:19 +0000343 } else {
344 oFsm.mutexUpgradeParams.Unlock()
345 logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
346 "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000347 }
348 return nil
349 }
350 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
351 "device-id": oFsm.deviceID})
352 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
353}
354
355//SetActivationParamsStart starts upgrade processing with immediate activation
356// called from 'new' API Activate_onu_image
357func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
358 oFsm.mutexUpgradeParams.Lock()
359 var pBaseFsm *fsm.FSM = nil
360 if oFsm.pAdaptFsm != nil {
361 pBaseFsm = oFsm.pAdaptFsm.pFsm
362 }
363 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
364 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
365 "device-id": oFsm.deviceID, "image-version": aImageVersion})
366 oFsm.useAPIVersion43 = true
367 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
368 oFsm.imageVersion = aImageVersion
369 oFsm.activateImage = true
370 oFsm.commitImage = aCommit
mpagenko38662d02021-08-11 09:45:19 +0000371 // indicate start of the upgrade activity
372 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
373 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE //as simply applied for inactive image
mpagenkoc26d4c02021-05-06 14:27:57 +0000374 oFsm.mutexUpgradeParams.Unlock()
375 //directly request the FSM to activate the image
376 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
377 return nil
378 }
379 oFsm.mutexUpgradeParams.Unlock()
380 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
381 "device-id": oFsm.deviceID})
382 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
383}
384
385//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
386// called from 'new' API Commit_onu_image
mpagenko38662d02021-08-11 09:45:19 +0000387func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
388 aImageIdentifier string, aImageVersion string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000389 oFsm.mutexUpgradeParams.Lock()
390 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
391 // (as long as the Imageidentifier is correct)
392 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
393 "device-id": oFsm.deviceID, "image-id": aImageIdentifier})
mpagenko38662d02021-08-11 09:45:19 +0000394 if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000395 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
mpagenko38662d02021-08-11 09:45:19 +0000396 "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
397 "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
mpagenkoc26d4c02021-05-06 14:27:57 +0000398 oFsm.mutexUpgradeParams.Unlock()
399 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
400 oFsm.deviceID))
401 }
402 oFsm.commitImage = true
mpagenko38662d02021-08-11 09:45:19 +0000403 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
mpagenkoc26d4c02021-05-06 14:27:57 +0000404 oFsm.mutexUpgradeParams.Unlock()
405 var pBaseFsm *fsm.FSM = nil
406 if oFsm.pAdaptFsm != nil {
407 pBaseFsm = oFsm.pAdaptFsm.pFsm
408 }
409 if pBaseFsm != nil {
mpagenko183647c2021-06-08 15:25:04 +0000410 //let the FSM decide if it is ready to process the event
411 logger.Debugw(ctx, "OnuUpgradeFsm requesting commit",
412 log.Fields{"device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
413 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000414 return nil
415 }
mpagenko38662d02021-08-11 09:45:19 +0000416 //should never occur
mpagenkoc26d4c02021-05-06 14:27:57 +0000417 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
418 "device-id": oFsm.deviceID})
419 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
420}
421
422//SetCommitmentParamsStart starts upgrade processing with immediate commitment
423// called from 'new' API Commit_onu_image
424func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
425 oFsm.mutexUpgradeParams.Lock()
426 var pBaseFsm *fsm.FSM = nil
427 if oFsm.pAdaptFsm != nil {
428 pBaseFsm = oFsm.pAdaptFsm.pFsm
429 }
430 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
431 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
432 "device-id": oFsm.deviceID, "image-version": aImageVersion})
433 oFsm.useAPIVersion43 = true
434 oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
435 oFsm.imageVersion = aImageVersion
436 oFsm.commitImage = true
mpagenko38662d02021-08-11 09:45:19 +0000437 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
438 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE //as simply applied for active image
mpagenkoc26d4c02021-05-06 14:27:57 +0000439 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +0000440 //directly request the FSM to commit the image
mpagenkoc26d4c02021-05-06 14:27:57 +0000441 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
442 return nil
443 }
444 oFsm.mutexUpgradeParams.Unlock()
445 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
446 "device-id": oFsm.deviceID})
447 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
448}
449
mpagenko1f8e8822021-06-25 14:10:21 +0000450//GetCommitFlag delivers the commit flag that was configured here
451func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
452 oFsm.mutexUpgradeParams.RLock()
453 defer oFsm.mutexUpgradeParams.RUnlock()
454 return oFsm.commitImage
455}
456
mpagenko38662d02021-08-11 09:45:19 +0000457//GetImageStates delivers the download/image states as per device proto buf definition
mpagenkoaa3afe92021-05-21 16:20:58 +0000458func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
mpagenko38662d02021-08-11 09:45:19 +0000459 aImageIdentifier string, aVersion string) *voltha.ImageState {
mpagenkoaa3afe92021-05-21 16:20:58 +0000460 pImageState := &voltha.ImageState{}
mpagenko38662d02021-08-11 09:45:19 +0000461 pImageState.Version = aVersion //version as requested
mpagenkoaa3afe92021-05-21 16:20:58 +0000462 // check if the request refers to some active image/version of the processing
463 oFsm.mutexUpgradeParams.RLock()
464 if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
465 pImageState.DownloadState = oFsm.volthaDownloadState
466 pImageState.Reason = oFsm.volthaDownloadReason
467 pImageState.ImageState = oFsm.volthaImageState
468 } else {
469 pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
470 pImageState.Reason = voltha.ImageState_NO_ERROR
471 pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
472 }
473 oFsm.mutexUpgradeParams.RUnlock()
mpagenko38662d02021-08-11 09:45:19 +0000474 return pImageState
mpagenkoaa3afe92021-05-21 16:20:58 +0000475}
476
mpagenko38662d02021-08-11 09:45:19 +0000477//GetSpecificImageState delivers ImageState of the download/image states as per device proto buf definition
478func (oFsm *OnuUpgradeFsm) GetSpecificImageState(ctx context.Context) voltha.ImageState_ImageActivationState {
479 oFsm.mutexUpgradeParams.RLock()
480 imageState := oFsm.volthaImageState
481 oFsm.mutexUpgradeParams.RUnlock()
482 return imageState
483}
484
485//SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
486func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
mpagenko183647c2021-06-08 15:25:04 +0000487 oFsm.mutexUpgradeParams.Lock()
488 defer oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +0000489 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
490 if !oFsm.commitImage {
491 //if commit is not additionally set, regard the upgrade activity as successful
492 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED //better choice would be 'UpgradeState=Succeeded'
493 }
494}
495
496//GetImageVersion delivers image-version of the running upgrade
497func (oFsm *OnuUpgradeFsm) GetImageVersion(ctx context.Context) string {
498 oFsm.mutexUpgradeParams.RLock()
499 imageVersion := oFsm.imageVersion
500 oFsm.mutexUpgradeParams.RUnlock()
501 return imageVersion
mpagenko183647c2021-06-08 15:25:04 +0000502}
503
mpagenkoc26d4c02021-05-06 14:27:57 +0000504//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko38662d02021-08-11 09:45:19 +0000505func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
506 aReason voltha.ImageState_ImageFailureReason) {
507 oFsm.mutexAbortRequest.Lock()
508 oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
509 oFsm.mutexAbortRequest.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000510 //mutex protection is required for possible concurrent access to FSM members
511 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
512 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
513 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
514 if oFsm.isWaitingForAdapterDlResponse {
515 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
516 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
517 oFsm.chAdapterDlReady <- false
518 } else {
519 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
520 }
521 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
522
523 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
mpagenko1f8e8822021-06-25 14:10:21 +0000524 // specific here: See definition of state changes: some states are excluded from reset for possible later commit
mpagenkoc26d4c02021-05-06 14:27:57 +0000525 pAdaptFsm := oFsm.pAdaptFsm
526 if pAdaptFsm != nil {
527 // calling FSM events in background to avoid blocking of the caller
528 go func(aPAFsm *AdapterFsm) {
529 if aPAFsm.pFsm != nil {
530 if aPAFsm.pFsm.Is(upgradeStWaitEndDL) {
mpagenko38662d02021-08-11 09:45:19 +0000531 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
mpagenkoc26d4c02021-05-06 14:27:57 +0000532 }
mpagenko38662d02021-08-11 09:45:19 +0000533 // in case of state-conditional request the
534
535 var err error
536 if abCompleteAbort {
537 oFsm.mutexUpgradeParams.Lock()
538 //any previous lingering conditional cancelRequest is superseded by this abortion
539 oFsm.conditionalCancelRequested = false
540 if aReason == voltha.ImageState_CANCELLED_ON_REQUEST {
541 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
542 } else {
543 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
544 }
545 oFsm.volthaDownloadReason = aReason
546 oFsm.mutexUpgradeParams.Unlock()
547 err = aPAFsm.pFsm.Event(upgradeEvAbort) //as unconditional default FSM cancellation
548 } else {
549 //at conditional request the image states are set when reaching the reset state
550 oFsm.conditionalCancelRequested = true
551 err = aPAFsm.pFsm.Event(upgradeEvReset) //as state-conditional default FSM cleanup
552 }
553 if err != nil {
554 //error return is expected in case of conditional request and no state transition
555 logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
556 "device-id": oFsm.deviceID, "error": err})
557 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000558 } //else the FSM seems already to be in some released state
559 }(pAdaptFsm)
560 }
561}
562
mpagenko80622a52021-02-09 16:53:23 +0000563func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
564 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
565 "device-id": oFsm.deviceID})
566
567 // start go routine for processing of LockState messages
568 go oFsm.processOmciUpgradeMessages(ctx)
569}
570
mpagenkoc26d4c02021-05-06 14:27:57 +0000571//enterWaitingAdapterDL state can only be reached with useAPIVersion43
572func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
573 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
574 "device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +0000575 syncChannel := make(chan struct{})
576 go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
577 //block until the wait routine is really blocked on chAdapterDlReady
578 <-syncChannel
mpagenkoc26d4c02021-05-06 14:27:57 +0000579 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
580}
581
mpagenko80622a52021-02-09 16:53:23 +0000582func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
583 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
584 "device-id": oFsm.deviceID})
585
mpagenkoc26d4c02021-05-06 14:27:57 +0000586 var fileLen int64
587 var err error
mpagenkoaa3afe92021-05-21 16:20:58 +0000588 oFsm.mutexUpgradeParams.Lock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000589 if oFsm.useAPIVersion43 {
590 //with the new API structure download to adapter is implicit and we have to wait until the image is available
591 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
592 } else {
593 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
594 }
mpagenko80622a52021-02-09 16:53:23 +0000595 if err != nil || fileLen > int64(cMaxUint32) {
mpagenko38662d02021-08-11 09:45:19 +0000596 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000597 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenko38662d02021-08-11 09:45:19 +0000598 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
mpagenkoaa3afe92021-05-21 16:20:58 +0000599 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000600 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
601 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
602 pBaseFsm := oFsm.pAdaptFsm
603 // Can't call FSM Event directly, decoupling it
604 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000605 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000606 }(pBaseFsm)
607 return
608 }
609
mpagenkoc26d4c02021-05-06 14:27:57 +0000610 //copy file content to buffer
mpagenko80622a52021-02-09 16:53:23 +0000611 oFsm.imageBuffer = make([]byte, fileLen)
mpagenkoc26d4c02021-05-06 14:27:57 +0000612 if oFsm.useAPIVersion43 {
613 oFsm.imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
614 } else {
615 oFsm.imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
616 }
mpagenko80622a52021-02-09 16:53:23 +0000617 if err != nil {
mpagenko38662d02021-08-11 09:45:19 +0000618 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000619 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenko38662d02021-08-11 09:45:19 +0000620 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
mpagenkoaa3afe92021-05-21 16:20:58 +0000621 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000622 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
623 "device-id": oFsm.deviceID, "error": err})
624 pBaseFsm := oFsm.pAdaptFsm
625 // Can't call FSM Event directly, decoupling it
626 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000627 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000628 }(pBaseFsm)
629 return
630 }
631
632 oFsm.noOfSections = uint32(fileLen / cOmciDownloadSectionSize)
633 if fileLen%cOmciDownloadSectionSize > 0 {
mpagenkoc26d4c02021-05-06 14:27:57 +0000634 bufferPadding := make([]byte, cOmciDownloadSectionSize-uint32((fileLen)%cOmciDownloadSectionSize))
mpagenko80622a52021-02-09 16:53:23 +0000635 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
mpagenkoc26d4c02021-05-06 14:27:57 +0000636 oFsm.imageBuffer = append(oFsm.imageBuffer[:(fileLen)], bufferPadding...)
mpagenko80622a52021-02-09 16:53:23 +0000637 oFsm.noOfSections++
638 }
639 oFsm.origImageLength = uint32(fileLen)
640 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000641 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
642 "MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
643 "ImageSize": oFsm.imageLength, "original file size": fileLen})
644 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
mpagenkoaa3afe92021-05-21 16:20:58 +0000645
646 oFsm.mutexUpgradeParams.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +0000647
648 // flush commMetricsChan
649 select {
650 case <-oFsm.chOnuDlReady:
651 logger.Debug(ctx, "flushed OnuDlReady channel")
652 default:
653 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000654 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
655
Girish Gowdra0b235842021-03-09 13:06:46 -0800656 err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000657 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
658 if err != nil {
659 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
660 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000661 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000662 return
663 }
664}
665
666func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
667 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
668 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
669
670 var windowAckRequest uint8 = 0
671 var bufferStartOffset uint32
672 var bufferEndOffset uint32
673 var downloadSection []byte
674 framePrint := false //default no printing of downloadSection frames
mpagenkoaa3afe92021-05-21 16:20:58 +0000675 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000676 if oFsm.nextDownloadSectionsAbsolute == 0 {
677 //debug print of first section frame
678 framePrint = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000679 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
mpagenko80622a52021-02-09 16:53:23 +0000680 }
681
682 for {
mpagenko38662d02021-08-11 09:45:19 +0000683 oFsm.mutexAbortRequest.RLock()
684 // this way out of the section download loop on abort request
685 if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
686 if oFsm.abortRequested == voltha.ImageState_CANCELLED_ON_REQUEST {
687 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
688 } else {
689 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
690 }
691 oFsm.volthaDownloadReason = oFsm.abortRequested
692 oFsm.mutexAbortRequest.RUnlock()
693 oFsm.mutexUpgradeParams.Unlock()
694 pBaseFsm := oFsm.pAdaptFsm
695 // Can't call FSM Event directly, decoupling it
696 go func(a_pAFsm *AdapterFsm) {
697 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
698 }(pBaseFsm)
699 return
700 }
701 oFsm.mutexAbortRequest.RUnlock()
702
mpagenko80622a52021-02-09 16:53:23 +0000703 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
704 bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
705 logger.Debugw(ctx, "DlSection values are", log.Fields{
706 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
707 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
708 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
709 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
710 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
711 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
712 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
mpagenko38662d02021-08-11 09:45:19 +0000713 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000714 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000715 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000716 //logical error -- reset the FSM
717 pBaseFsm := oFsm.pAdaptFsm
718 // Can't call FSM Event directly, decoupling it
719 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000720 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000721 }(pBaseFsm)
722 return
723 }
724 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
725 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
726 windowAckRequest = 1
727 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
728 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
729 }
730 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
731 windowAckRequest = 1
732 framePrint = true //debug print of last frame
mpagenko15ff4a52021-03-02 10:09:20 +0000733 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
734 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000735 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
736 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000737 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
Girish Gowdra0b235842021-03-09 13:06:46 -0800738 err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000739 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
740 if err != nil {
741 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000742 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000743 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000744 return
745 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000746 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000747 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
748 if windowAckRequest == 1 {
749 pBaseFsm := oFsm.pAdaptFsm
750 // Can't call FSM Event directly, decoupling it
mpagenkoaa3afe92021-05-21 16:20:58 +0000751 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000752 go func(a_pAFsm *AdapterFsm) {
753 _ = a_pAFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
754 }(pBaseFsm)
755 return
756 }
757 framePrint = false //for the next Section frame (if wanted, can be enabled in logic before sendXXX())
758 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000759 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000760 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenkoaa3afe92021-05-21 16:20:58 +0000761 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko59498c12021-03-18 14:15:15 +0000762 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenkoaa3afe92021-05-21 16:20:58 +0000763 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000764 }
765 }
766}
767
768func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
769 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
770 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
771}
772
773func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000774 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000775 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
mpagenko80622a52021-02-09 16:53:23 +0000776
mpagenkoaa3afe92021-05-21 16:20:58 +0000777 oFsm.mutexUpgradeParams.RLock()
mpagenko80622a52021-02-09 16:53:23 +0000778 if oFsm.delayEndSwDl {
mpagenkoaa3afe92021-05-21 16:20:58 +0000779 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000780 //give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
781 // should not be set in case this state is used for real download abort (not yet implemented)
782 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoaa3afe92021-05-21 16:20:58 +0000783 } else {
784 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000785 }
786
mpagenko59498c12021-03-18 14:15:15 +0000787 pBaseFsm := oFsm.pAdaptFsm
788 if pBaseFsm == nil {
mpagenko38662d02021-08-11 09:45:19 +0000789 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
790 oFsm.mutexUpgradeParams.Lock()
791 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
792 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
793 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000794 // Can't call FSM Event directly, decoupling it
795 go func(a_pAFsm *AdapterFsm) {
796 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
797 }(pBaseFsm)
798 return
799 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800800 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko59498c12021-03-18 14:15:15 +0000801 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.origImageLength, oFsm.imageCRC)
mpagenko80622a52021-02-09 16:53:23 +0000802 if err != nil {
803 logger.Errorw(ctx, "EndSwDl abort: can't send section", log.Fields{
804 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000805 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000806 return
807 }
mpagenko59498c12021-03-18 14:15:15 +0000808 // go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
809 // Can't call FSM Event directly, decoupling it
810 go func(a_pAFsm *AdapterFsm) {
811 _ = a_pAFsm.pFsm.Event(upgradeEvWaitEndDownload)
812 }(pBaseFsm)
813}
814
815func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
816 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
817 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
818 if oFsm.waitCountEndSwDl == 0 {
819 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
820 "device-id": oFsm.deviceID})
821 pBaseFsm := oFsm.pAdaptFsm
822 if pBaseFsm == nil {
823 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
824 "device-id": oFsm.deviceID})
825 return
826 }
mpagenko38662d02021-08-11 09:45:19 +0000827 oFsm.mutexUpgradeParams.Lock()
828 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000829 oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
mpagenko38662d02021-08-11 09:45:19 +0000830 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000831 go func(a_pAFsm *AdapterFsm) {
832 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
833 }(pBaseFsm)
834 return
835 }
836
837 oFsm.waitCountEndSwDl--
838 select {
839 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
840 pBaseFsm := oFsm.pAdaptFsm
841 if pBaseFsm == nil {
842 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
843 "device-id": oFsm.deviceID})
844 //FSM may be reset already from somewhere else, nothing we can do here anymore
845 return
846 }
847 //retry End SW DL
mpagenkoaa3afe92021-05-21 16:20:58 +0000848 oFsm.mutexUpgradeParams.Lock()
mpagenko59498c12021-03-18 14:15:15 +0000849 oFsm.delayEndSwDl = false //no more extra delay for the request
mpagenkoaa3afe92021-05-21 16:20:58 +0000850 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000851 go func(a_pAFsm *AdapterFsm) {
852 _ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
853 }(pBaseFsm)
854 return
855 case success := <-oFsm.chReceiveExpectedResponse:
856 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
857 pBaseFsm := oFsm.pAdaptFsm
858 if pBaseFsm == nil {
859 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
860 "device-id": oFsm.deviceID})
861 //FSM may be reset already from somewhere else, nothing we can do here anymore
862 return
863 }
864 if success {
865 //answer received with ready indication
mpagenko38662d02021-08-11 09:45:19 +0000866 //useAPIVersion43 may not conflict in concurrency in this state function
867 if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
mpagenkoc26d4c02021-05-06 14:27:57 +0000868 go func(a_pAFsm *AdapterFsm) {
mpagenko38662d02021-08-11 09:45:19 +0000869 _ = a_pAFsm.pFsm.Event(upgradeEvCheckImageName)
mpagenkoc26d4c02021-05-06 14:27:57 +0000870 }(pBaseFsm)
mpagenko38662d02021-08-11 09:45:19 +0000871 } else { // elder API usage does not support image version check -immediately consider download as successful
872 if oFsm.activateImage {
873 //immediate activation requested
874 go func(a_pAFsm *AdapterFsm) {
875 _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
876 }(pBaseFsm)
877 } else {
878 //have to wait on explicit activation request
879 go func(a_pAFsm *AdapterFsm) {
880 _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
881 }(pBaseFsm)
882 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000883 }
mpagenko59498c12021-03-18 14:15:15 +0000884 return
885 }
886 //timer was aborted
mpagenko38662d02021-08-11 09:45:19 +0000887 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko59498c12021-03-18 14:15:15 +0000888 return
889 }
mpagenko80622a52021-02-09 16:53:23 +0000890}
891
mpagenko38662d02021-08-11 09:45:19 +0000892func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
893 logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
894 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
895 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
896 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
897 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
898 false, oFsm.pAdaptFsm.commChan)
899 if err != nil {
900 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
901 log.Fields{"device-id": oFsm.deviceID, "Error": err})
902 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
903 return
904 }
905 oFsm.pLastTxMeInstance = meInstance
906}
907
mpagenko80622a52021-02-09 16:53:23 +0000908func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
909 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
910 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
911
Girish Gowdra0b235842021-03-09 13:06:46 -0800912 err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000913 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
914 if err != nil {
915 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
916 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000917 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +0000918 return
919 }
mpagenko38662d02021-08-11 09:45:19 +0000920 oFsm.mutexUpgradeParams.Lock()
921 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
922 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000923}
924
925func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +0000926 logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
927 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
928 //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
929 // (which is a bit problematic as the ONU might already be in committed state,
930 // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
931 if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
mpagenkoaa3afe92021-05-21 16:20:58 +0000932 oFsm.mutexUpgradeParams.Lock()
mpagenko38662d02021-08-11 09:45:19 +0000933 if activeImageID == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +0000934 inactiveImageID := oFsm.inactiveImageMeID
mpagenko15ff4a52021-03-02 10:09:20 +0000935 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
mpagenkoaa3afe92021-05-21 16:20:58 +0000936 "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
937 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
938 oFsm.mutexUpgradeParams.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800939 err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenkoaa3afe92021-05-21 16:20:58 +0000940 oFsm.pAdaptFsm.commChan, inactiveImageID) //more efficient activeImageID with above check
mpagenko15ff4a52021-03-02 10:09:20 +0000941 if err != nil {
942 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
943 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000944 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +0000945 return
946 }
947 return
948 }
mpagenko38662d02021-08-11 09:45:19 +0000949 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000950 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
951 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
mpagenko38662d02021-08-11 09:45:19 +0000952 } else {
953 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
954 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000955 }
mpagenko38662d02021-08-11 09:45:19 +0000956 oFsm.mutexUpgradeParams.Lock()
957 oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
958 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
959 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
960 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
961 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000962 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
963 pBaseFsm := oFsm.pAdaptFsm
964 // Can't call FSM Event directly, decoupling it
965 go func(a_pAFsm *AdapterFsm) {
966 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
967 }(pBaseFsm)
968}
969
970func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +0000971 logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000972 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
mpagenko15ff4a52021-03-02 10:09:20 +0000973 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
ozgecanetsiab36ed572021-04-01 10:38:48 +0300974 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
Girish Gowdra0b235842021-03-09 13:06:46 -0800975 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300976 if err != nil {
977 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
978 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko38662d02021-08-11 09:45:19 +0000979 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300980 return
981 }
mpagenko15ff4a52021-03-02 10:09:20 +0000982 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +0000983}
984
985func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
986 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
987
mpagenko38662d02021-08-11 09:45:19 +0000988 // if the reset was conditionally requested
989 if oFsm.conditionalCancelRequested {
990 oFsm.mutexUpgradeParams.Lock()
991 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
992 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
993 oFsm.mutexUpgradeParams.Unlock()
994 }
995
mpagenkoc26d4c02021-05-06 14:27:57 +0000996 // in case the download-to-ONU timer is still running - cancel it
mpagenko39b703e2021-08-25 13:38:40 +0000997 //use non-blocking channel (to be independent from receiver state)
998 select {
999 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1000 case oFsm.chOnuDlReady <- false:
1001 default:
mpagenkoc26d4c02021-05-06 14:27:57 +00001002 }
1003
mpagenko80622a52021-02-09 16:53:23 +00001004 pConfigupgradeStateAFsm := oFsm.pAdaptFsm
1005 if pConfigupgradeStateAFsm != nil {
1006 // abort running message processing
1007 fsmAbortMsg := Message{
1008 Type: TestMsg,
1009 Data: TestMessage{
1010 TestMessageVal: AbortMessageProcessing,
1011 },
1012 }
1013 pConfigupgradeStateAFsm.commChan <- fsmAbortMsg
1014
1015 //try to restart the FSM to 'disabled'
1016 // Can't call FSM Event directly, decoupling it
1017 go func(a_pAFsm *AdapterFsm) {
1018 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1019 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1020 }
1021 }(pConfigupgradeStateAFsm)
1022 }
1023}
1024
1025func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1026 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001027 // no need to flush possible channels here, Upgrade FSM will be completely removed, garbage collector should find its way
mpagenko80622a52021-02-09 16:53:23 +00001028 if oFsm.pDeviceHandler != nil {
1029 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenko38662d02021-08-11 09:45:19 +00001030 pLastUpgradeImageState := &voltha.ImageState{
1031 Version: oFsm.imageVersion,
1032 DownloadState: oFsm.volthaDownloadState,
1033 Reason: oFsm.volthaDownloadReason,
1034 ImageState: oFsm.volthaImageState,
1035 }
1036 go oFsm.pDeviceHandler.removeOnuUpgradeFsm(ctx, pLastUpgradeImageState)
mpagenko80622a52021-02-09 16:53:23 +00001037 }
1038}
1039
1040func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
1041 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
1042loop:
1043 for {
1044 // case <-ctx.Done():
1045 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
1046 // break loop
1047 message, ok := <-oFsm.pAdaptFsm.commChan
1048 if !ok {
1049 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
1050 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko38662d02021-08-11 09:45:19 +00001051 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +00001052 break loop
1053 }
1054 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
1055
1056 switch message.Type {
1057 case TestMsg:
1058 msg, _ := message.Data.(TestMessage)
1059 if msg.TestMessageVal == AbortMessageProcessing {
1060 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
1061 break loop
1062 }
1063 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
1064 case OMCI:
1065 msg, _ := message.Data.(OmciMessage)
1066 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
1067 default:
1068 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
1069 "message.Type": message.Type})
1070 }
1071 }
1072 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
1073}
1074
1075//nolint: gocyclo
1076func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg OmciMessage) {
1077 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
1078 "msgType": msg.OmciMsg.MessageType})
1079
1080 switch msg.OmciMsg.MessageType {
1081 case omci.StartSoftwareDownloadResponseType:
1082 {
1083 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
1084 if msgLayer == nil {
1085 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
1086 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001087 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001088 return
1089 }
1090 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
1091 if !msgOk {
1092 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
1093 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001094 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001095 return
1096 }
1097 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
1098 "device-id": oFsm.deviceID, "data-fields": msgObj})
1099 if msgObj.Result != me.Success {
1100 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
1101 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001102 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001103 return
1104 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001105
1106 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001107 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1108 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1109 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
1110 // also response WindowSize = 0 is a valid number for used Window size 1
1111 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
1112 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
1113 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
1114 }
1115 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
1116 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
1117 oFsm.noOfWindows++
1118 }
1119 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
1120 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
1121 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
1122 oFsm.nextDownloadSectionsAbsolute = 0
1123 oFsm.nextDownloadSectionsWindow = 0
1124 oFsm.nextDownloadWindow = 0
1125
mpagenkoaa3afe92021-05-21 16:20:58 +00001126 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001127 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
1128 return
1129 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001130 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001131 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1132 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001133 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001134 return
1135 } //StartSoftwareDownloadResponseType
1136 case omci.DownloadSectionResponseType:
1137 {
mpagenko80622a52021-02-09 16:53:23 +00001138 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
1139 if msgLayer == nil {
1140 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
1141 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
mpagenko38662d02021-08-11 09:45:19 +00001142 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001143 return
1144 }
1145 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
1146 if !msgOk {
1147 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
1148 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001149 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001150 return
1151 }
1152 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
1153 "device-id": oFsm.deviceID, "data-fields": msgObj})
1154 if msgObj.Result != me.Success {
1155 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
1156 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001157 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001158 return
1159 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001160 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001161 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1162 sectionNumber := msgObj.SectionNumber
mpagenko15ff4a52021-03-02 10:09:20 +00001163 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
1164 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +00001165
mpagenko15ff4a52021-03-02 10:09:20 +00001166 oFsm.nextDownloadWindow++
1167 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
1168 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
mpagenko02cf1b22021-03-12 17:30:30 +00001169 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
mpagenko15ff4a52021-03-02 10:09:20 +00001170 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
1171 "expected section": oFsm.omciDownloadWindowSizeLast})
mpagenkoaa3afe92021-05-21 16:20:58 +00001172 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001173 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko15ff4a52021-03-02 10:09:20 +00001174 return
1175 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001176 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
1177 //CRC computation for all data bytes of the file
1178 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
1179 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
1180 var byteSlice []byte = make([]byte, 4)
1181 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
1182 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
mpagenkoaa3afe92021-05-21 16:20:58 +00001183 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001184 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
1185 return
1186 }
1187 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
1188 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
mpagenko02cf1b22021-03-12 17:30:30 +00001189 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
1190 "expected section": oFsm.omciDownloadWindowSizeLimit})
mpagenkoaa3afe92021-05-21 16:20:58 +00001191 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001192 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko15ff4a52021-03-02 10:09:20 +00001193 return
1194 }
1195 oFsm.nextDownloadSectionsWindow = 0
mpagenkoaa3afe92021-05-21 16:20:58 +00001196 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001197 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
mpagenko80622a52021-02-09 16:53:23 +00001198 return
1199 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001200 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001201 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1202 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001203 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001204 return
mpagenko80622a52021-02-09 16:53:23 +00001205 } //DownloadSectionResponseType
1206 case omci.EndSoftwareDownloadResponseType:
1207 {
1208 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1209 if msgLayer == nil {
1210 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1211 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001212 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001213 return
1214 }
1215 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1216 if !msgOk {
1217 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1218 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001219 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001220 return
1221 }
1222 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1223 "device-id": oFsm.deviceID, "data-fields": msgObj})
1224 if msgObj.Result != me.Success {
mpagenko59498c12021-03-18 14:15:15 +00001225 if msgObj.Result == me.DeviceBusy {
1226 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1227 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1228 "device-id": oFsm.deviceID})
1229 return
1230 }
mpagenko80622a52021-02-09 16:53:23 +00001231 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
1232 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001233 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001234 return
1235 }
mpagenko183647c2021-06-08 15:25:04 +00001236 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001237 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko38662d02021-08-11 09:45:19 +00001238 //EndSwDownloadSuccess is used to indicate 'DOWNLOAD_SUCCEEDED'
mpagenko183647c2021-06-08 15:25:04 +00001239 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
mpagenko38662d02021-08-11 09:45:19 +00001240 if !oFsm.useAPIVersion43 {
1241 //in the older API version the image version check was not possible
1242 // - assume new loaded image as valid-inactive immediately
1243 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1244 oFsm.mutexUpgradeParams.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +00001245 //use non-blocking channel (to be independent from receiver state)
1246 select {
1247 //use non-blocking channel to indicate that the download to ONU was successful
1248 case oFsm.chOnuDlReady <- true:
1249 default:
mpagenko38662d02021-08-11 09:45:19 +00001250 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001251 } else {
mpagenko38662d02021-08-11 09:45:19 +00001252 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001253 }
mpagenko38662d02021-08-11 09:45:19 +00001254 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1255 //use non-blocking channel to let the FSM proceed from the waitState
1256 select {
1257 case oFsm.chReceiveExpectedResponse <- true:
1258 default:
1259 }
mpagenko80622a52021-02-09 16:53:23 +00001260 return
1261 }
mpagenko183647c2021-06-08 15:25:04 +00001262 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001263 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1264 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001265 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001266 return
1267 } //EndSoftwareDownloadResponseType
1268 case omci.ActivateSoftwareResponseType:
1269 {
1270 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1271 if msgLayer == nil {
1272 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1273 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001274 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001275 return
1276 }
1277 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1278 if !msgOk {
1279 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1280 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001281 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001282 return
1283 }
1284 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1285 "device-id": oFsm.deviceID, "data-fields": msgObj})
1286 if msgObj.Result != me.Success {
1287 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1288 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001289 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001290 return
1291 }
mpagenko183647c2021-06-08 15:25:04 +00001292 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001293 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko38662d02021-08-11 09:45:19 +00001294 // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
mpagenko183647c2021-06-08 15:25:04 +00001295 oFsm.mutexUpgradeParams.Unlock()
1296 logger.Infow(ctx, "Expected ActivateSwResponse received",
1297 log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
1298 if oFsm.commitImage {
1299 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
1300 } else {
1301 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvActivationDone) // let the FSM wait for external commit request
1302 }
mpagenko80622a52021-02-09 16:53:23 +00001303 return
1304 }
mpagenko183647c2021-06-08 15:25:04 +00001305 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001306 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1307 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001308 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001309 return
1310 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001311 case omci.CommitSoftwareResponseType:
1312 {
1313 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1314 if msgLayer == nil {
1315 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1316 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001317 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001318 return
1319 }
1320 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1321 if !msgOk {
1322 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1323 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001324 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001325 return
1326 }
mpagenkobf67a092021-03-17 09:52:28 +00001327 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001328 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1329 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001330 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001331 return
mpagenkobf67a092021-03-17 09:52:28 +00001332 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001333 oFsm.mutexUpgradeParams.RLock()
mpagenko15ff4a52021-03-02 10:09:20 +00001334 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001335 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001336 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1337 //verifying committed image
1338 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
1339 return
1340 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001341 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001342 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1343 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001344 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001345 return
1346 } //CommitSoftwareResponseType
1347 case omci.GetResponseType:
1348 {
1349 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1350 if msgLayer == nil {
1351 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1352 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001353 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001354 return
1355 }
1356 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1357 if !msgOk {
1358 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1359 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001360 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001361 return
1362 }
1363 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1364 "device-id": oFsm.deviceID, "data-fields": msgObj})
1365 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1366 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1367 if msgObj.Result != me.Success {
1368 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1369 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001370 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001371 return
1372 }
1373 } else {
1374 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1375 log.Fields{"device-id": oFsm.deviceID})
1376 return
1377 }
1378
1379 meAttributes := msgObj.Attributes
1380 imageIsCommitted := meAttributes["IsCommitted"].(uint8)
1381 imageIsActive := meAttributes["IsActive"].(uint8)
Holger Hildebrandtfb402a62021-05-26 14:40:49 +00001382 imageVersion := TrimStringFromMeOctet(meAttributes["Version"])
mpagenko02cf1b22021-03-12 17:30:30 +00001383 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
mpagenko15ff4a52021-03-02 10:09:20 +00001384 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1385 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
mpagenkoaa3afe92021-05-21 16:20:58 +00001386
mpagenko38662d02021-08-11 09:45:19 +00001387 if oFsm.pAdaptFsm.pFsm.Current() == upgradeStCheckImageName {
1388 //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
1389 oFsm.mutexUpgradeParams.Lock()
1390 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsInactive &&
1391 imageIsCommitted == swIsUncommitted {
1392 if imageVersion != oFsm.imageVersion {
1393 //new stored inactive version indicated on OMCI from ONU is not the expected version
1394 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
1395 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1396 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1397 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was downloaded
1398 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1399 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'DOWNLOADED' would be better - proto def
1400 oFsm.mutexUpgradeParams.Unlock()
1401 //stop the running ONU download timer
mpagenko39b703e2021-08-25 13:38:40 +00001402 //use non-blocking channel (to be independent from receiver state)
1403 select {
1404 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1405 case oFsm.chOnuDlReady <- false:
1406 default:
mpagenko38662d02021-08-11 09:45:19 +00001407 }
1408 // TODO!!!: error treatment?
1409 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1410 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1411 return
1412 }
1413 //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
1414 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1415 //store the new inactive version to onuSwImageIndications (to keep them in sync)
1416 oFsm.pDevEntry.modifySwImageInactiveVersion(ctx, oFsm.imageVersion)
1417 //proceed within upgrade FSM
1418 if oFsm.activateImage {
1419 //immediate activation requested
1420 oFsm.mutexUpgradeParams.Unlock()
1421 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
1422 log.Fields{"device-id": oFsm.deviceID})
1423 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRequestActivate)
1424 } else {
1425 //have to wait on explicit activation request
1426 // but a previously requested download activity (without activation) was successful here
1427 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1428 oFsm.mutexUpgradeParams.Unlock()
1429 logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
1430 log.Fields{"device-id": oFsm.deviceID})
1431 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForActivate)
1432 }
mpagenko39b703e2021-08-25 13:38:40 +00001433 //use non-blocking channel (to be independent from receiver state)
1434 select {
1435 //use non-blocking channel to indicate that the download to ONU was successful
1436 case oFsm.chOnuDlReady <- true:
1437 default:
mpagenko38662d02021-08-11 09:45:19 +00001438 }
1439 return
1440 }
1441 //not the expected image/image state
1442 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1443 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1444 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //real image state not known
1445 oFsm.mutexUpgradeParams.Unlock()
1446 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1447 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1448 // TODO!!!: error treatment?
1449 //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
1450 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1451 return
1452 }
1453
1454 //assumed only relevant state here is upgradeStCheckCommitted
mpagenkoaa3afe92021-05-21 16:20:58 +00001455 oFsm.mutexUpgradeParams.Lock()
mpagenko38662d02021-08-11 09:45:19 +00001456 oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
mpagenkoaa3afe92021-05-21 16:20:58 +00001457 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive {
mpagenkoc26d4c02021-05-06 14:27:57 +00001458 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1459 // indicated in the download image version string (version must be part of the image content itself)
1460 // so checking that might be quite unreliable
1461 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1462 // in all the API references, so it can and should be checked here now
1463 if oFsm.useAPIVersion43 {
1464 if imageVersion != oFsm.imageVersion {
1465 //new active version indicated on OMCI from ONU is not the expected version
mpagenko38662d02021-08-11 09:45:19 +00001466 logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
mpagenkoc26d4c02021-05-06 14:27:57 +00001467 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1468 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1469 // TODO!!!: error treatment?
mpagenko38662d02021-08-11 09:45:19 +00001470 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1471 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was committed
1472 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1473 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //expected image not known
1474 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001475 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1476 return
1477 }
1478 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1479 log.Fields{"device-id": oFsm.deviceID})
1480 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001481 if imageIsCommitted == swIsCommitted {
mpagenko38662d02021-08-11 09:45:19 +00001482 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
mpagenkoaa3afe92021-05-21 16:20:58 +00001483 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
mpagenko38662d02021-08-11 09:45:19 +00001484 //store the new commit flag to onuSwImageIndications (to keep them in sync)
1485 oFsm.pDevEntry.modifySwImageActiveCommit(ctx, imageIsCommitted)
mpagenkoaa3afe92021-05-21 16:20:58 +00001486 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001487 //deviceProcStatusUpdate not used anymore,
1488 // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
mpagenkoaa3afe92021-05-21 16:20:58 +00001489 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001490 //releasing the upgrade FSM on success
mpagenko183647c2021-06-08 15:25:04 +00001491 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenkoaa3afe92021-05-21 16:20:58 +00001492 return
1493 }
mpagenko38662d02021-08-11 09:45:19 +00001494 //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
mpagenko15ff4a52021-03-02 10:09:20 +00001495 }
mpagenko38662d02021-08-11 09:45:19 +00001496 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1497 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1498 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
mpagenkoaa3afe92021-05-21 16:20:58 +00001499 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001500 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1501 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1502 // TODO!!!: error treatment?
1503 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1504 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1505 return
1506 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001507 default:
1508 {
1509 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1510 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1511 return
1512 }
1513 }
1514}
1515
mpagenko38662d02021-08-11 09:45:19 +00001516//abortOnOmciError aborts the upgrade processing with OMCI_TRANSFER_ERROR indication
1517func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool,
1518 aImageState voltha.ImageState_ImageActivationState) {
1519 oFsm.mutexUpgradeParams.Lock()
1520 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1521 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1522 oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
1523 if aImageState != voltha.ImageState_IMAGE_UNKNOWN {
1524 // update image state only in case some explicite state is given (otherwise the existing state is used)
1525 oFsm.volthaImageState = aImageState
1526 }
1527 oFsm.mutexUpgradeParams.Unlock()
1528 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1529 if oFsm.pAdaptFsm != nil {
1530 var err error
1531 if aAsync { //asynchronous call requested to ensure state transition
1532 go func(a_pAFsm *AdapterFsm) {
1533 if a_pAFsm.pFsm != nil {
1534 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1535 }
1536 }(oFsm.pAdaptFsm)
1537 } else {
1538 if oFsm.pAdaptFsm.pFsm != nil {
1539 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1540 }
1541 }
1542 if err != nil {
1543 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1544 "device-id": oFsm.deviceID, "error": err})
1545 }
1546 }
1547}
1548
mpagenkoc26d4c02021-05-06 14:27:57 +00001549//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
mpagenko38662d02021-08-11 09:45:19 +00001550// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
1551func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
1552 aWaitChannel chan bool) {
mpagenkoc26d4c02021-05-06 14:27:57 +00001553 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
mpagenko38662d02021-08-11 09:45:19 +00001554 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
mpagenkoc26d4c02021-05-06 14:27:57 +00001555 oFsm.isWaitingForAdapterDlResponse = true
1556 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001557 aSyncChannel <- struct{}{}
mpagenko80622a52021-02-09 16:53:23 +00001558 select {
1559 // maybe be also some outside cancel (but no context modeled for the moment ...)
1560 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001561 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1562 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1563 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1564 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1565 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
mpagenko39b703e2021-08-25 13:38:40 +00001566 //running into timeout here may still have the download to adapter active -> abort
1567 oFsm.pFileManager.CancelDownload(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +00001568 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1569 oFsm.isWaitingForAdapterDlResponse = false
1570 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +00001571 oFsm.mutexUpgradeParams.Lock()
1572 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1573 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1574 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'DOWNLOAD_TO_ADAPTER_TIMEOUT' would be better (proto)
1575 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1576 oFsm.mutexUpgradeParams.Unlock()
1577 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1578 if oFsm.pAdaptFsm != nil && oFsm.pAdaptFsm.pFsm != nil {
1579 err := oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1580 if err != nil {
1581 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1582 "device-id": oFsm.deviceID, "error": err})
1583 }
1584 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001585 return
1586
1587 case success := <-aWaitChannel:
1588 if success {
1589 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1590 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1591 oFsm.isWaitingForAdapterDlResponse = false
1592 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1593 //let the upgrade process proceed
1594 pUpgradeFsm := oFsm.pAdaptFsm
1595 if pUpgradeFsm != nil {
1596 _ = pUpgradeFsm.pFsm.Event(upgradeEvPrepareSwDownload)
1597 } else {
1598 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1599 }
1600 return
1601 }
mpagenko39b703e2021-08-25 13:38:40 +00001602 // waiting was aborted (assumed here to be caused by
1603 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001604 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1605 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1606 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1607 oFsm.isWaitingForAdapterDlResponse = false
1608 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001609 return
mpagenko80622a52021-02-09 16:53:23 +00001610 }
1611}
mpagenkoc26d4c02021-05-06 14:27:57 +00001612
1613//waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1614func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1615 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1616 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1617 "duration": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001618 select {
1619 // maybe be also some outside cancel (but no context modeled for the moment ...)
1620 // case <-ctx.Done():
1621 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1622 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1623 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1624 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001625 //the upgrade process has to be aborted
mpagenko39b703e2021-08-25 13:38:40 +00001626 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenkoc26d4c02021-05-06 14:27:57 +00001627 return
1628
1629 case success := <-aWaitChannel:
1630 if success {
1631 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001632 //all fine, let the FSM proceed like defined from the sender of this event
1633 return
1634 }
1635 // waiting was aborted (assumed here to be caused by
mpagenko39b703e2021-08-25 13:38:40 +00001636 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001637 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001638 return
1639 }
1640}