blob: b4c4d3526046117279ba014bf49a24d5c0f244d3 [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
138 mutexIsAwaitingOnuDlResponse sync.RWMutex
139 chOnuDlReady chan bool
140 isWaitingForOnuDlResponse bool
141 activateImage bool
142 commitImage bool
mpagenko38662d02021-08-11 09:45:19 +0000143 mutexAbortRequest sync.RWMutex
144 abortRequested voltha.ImageState_ImageFailureReason
145 conditionalCancelRequested bool
mpagenkoaa3afe92021-05-21 16:20:58 +0000146 volthaDownloadState voltha.ImageState_ImageDownloadState
147 volthaDownloadReason voltha.ImageState_ImageFailureReason
148 volthaImageState voltha.ImageState_ImageActivationState
mpagenko80622a52021-02-09 16:53:23 +0000149}
150
151//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
152// of ONU UNI ports via OMCI
153func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler *deviceHandler,
mpagenko15ff4a52021-03-02 10:09:20 +0000154 apDevEntry *OnuDeviceEntry, apOnuDB *onuDeviceDB,
mpagenko80622a52021-02-09 16:53:23 +0000155 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message) *OnuUpgradeFsm {
156 instFsm := &OnuUpgradeFsm{
mpagenko59498c12021-03-18 14:15:15 +0000157 pDeviceHandler: apDeviceHandler,
158 deviceID: apDeviceHandler.deviceID,
mpagenko38662d02021-08-11 09:45:19 +0000159 pDevEntry: apDevEntry,
mpagenko59498c12021-03-18 14:15:15 +0000160 pOmciCC: apDevEntry.PDevOmciCC,
161 pOnuDB: apOnuDB,
162 requestEvent: aRequestEvent,
163 omciDownloadWindowSizeLimit: cOmciDownloadWindowSizeLimit,
164 omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000165 downloadToOnuTimeout4MB: apDeviceHandler.pOpenOnuAc.dlToOnuTimeout4M,
mpagenko59498c12021-03-18 14:15:15 +0000166 waitCountEndSwDl: cWaitCountEndSwDl,
167 waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
mpagenkoaa3afe92021-05-21 16:20:58 +0000168 volthaDownloadState: voltha.ImageState_DOWNLOAD_STARTED, //if FSM created we can assume that the download (to adapter) really started
169 volthaDownloadReason: voltha.ImageState_NO_ERROR,
170 volthaImageState: voltha.ImageState_IMAGE_UNKNOWN,
mpagenko38662d02021-08-11 09:45:19 +0000171 abortRequested: voltha.ImageState_NO_ERROR,
mpagenko80622a52021-02-09 16:53:23 +0000172 }
mpagenko59498c12021-03-18 14:15:15 +0000173 instFsm.chReceiveExpectedResponse = make(chan bool)
mpagenkoc26d4c02021-05-06 14:27:57 +0000174 instFsm.chAdapterDlReady = make(chan bool)
175 instFsm.chOnuDlReady = make(chan bool)
mpagenko80622a52021-02-09 16:53:23 +0000176
177 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
178 if instFsm.pAdaptFsm == nil {
179 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
180 "device-id": instFsm.deviceID})
181 return nil
182 }
183 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
184 upgradeStDisabled,
185 fsm.Events{
186 {Name: upgradeEvStart, Src: []string{upgradeStDisabled}, Dst: upgradeStStarting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000187 {Name: upgradeEvAdapterDownload, Src: []string{upgradeStStarting}, Dst: upgradeStWaitingAdapterDL},
188 {Name: upgradeEvPrepareSwDownload, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL}, Dst: upgradeStPreparingDL},
mpagenko80622a52021-02-09 16:53:23 +0000189 {Name: upgradeEvRxStartSwDownload, Src: []string{upgradeStPreparingDL}, Dst: upgradeStDLSection},
190 {Name: upgradeEvWaitWindowAck, Src: []string{upgradeStDLSection}, Dst: upgradeStVerifyWindow},
191 {Name: upgradeEvContinueNextWindow, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStDLSection},
192 {Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
mpagenko59498c12021-03-18 14:15:15 +0000193 {Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
194 {Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
mpagenko38662d02021-08-11 09:45:19 +0000195 //upgradeStCheckImageName only used with useAPIVersion43
196 {Name: upgradeEvCheckImageName, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStCheckImageName},
197 //upgradeEvWaitForActivate state transitions depend on useAPIVersion43
198 {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL, upgradeStCheckImageName}, Dst: upgradeStWaitForActivate},
199 //upgradeEvRequestActivate state transitions depend on useAPIVersion43
200 {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStCheckImageName,
201 upgradeStWaitForActivate}, Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
mpagenko183647c2021-06-08 15:25:04 +0000202 {Name: upgradeEvActivationDone, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStActivated},
mpagenko80622a52021-02-09 16:53:23 +0000203 {Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
mpagenko1f8e8822021-06-25 14:10:21 +0000204 {Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
205 upgradeStActivated}, Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
mpagenko15ff4a52021-03-02 10:09:20 +0000206 {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000207
208 /*
209 {Name: upgradeEvTimeoutSimple, Src: []string{
210 upgradeStCreatingDot1PMapper, upgradeStCreatingMBPCD, upgradeStSettingTconts, upgradeStSettingDot1PMapper}, Dst: upgradeStStarting},
211 {Name: upgradeEvTimeoutMids, Src: []string{
212 upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
213 */
214 // exceptional treatments
mpagenko1f8e8822021-06-25 14:10:21 +0000215 //on upgradeEvReset: upgradeStRequestingActivate, upgradeStWaitForCommit and upgradeStActivated are not reset
216 // (to let the FSM survive the expected OnuDown indication)
mpagenkoc26d4c02021-05-06 14:27:57 +0000217 {Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko38662d02021-08-11 09:45:19 +0000218 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
219 upgradeStWaitForActivate,
mpagenko1f8e8822021-06-25 14:10:21 +0000220 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000221 Dst: upgradeStResetting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000222 {Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko38662d02021-08-11 09:45:19 +0000223 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
224 upgradeStWaitForActivate,
225 upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit,
226 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000227 Dst: upgradeStResetting},
228 {Name: upgradeEvRestart, Src: []string{upgradeStResetting}, Dst: upgradeStDisabled},
229 },
230 fsm.Callbacks{
231 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
232 "enter_" + upgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
mpagenkoc26d4c02021-05-06 14:27:57 +0000233 "enter_" + upgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000234 "enter_" + upgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
235 "enter_" + upgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
236 "enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
237 "enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
mpagenko59498c12021-03-18 14:15:15 +0000238 "enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
mpagenko38662d02021-08-11 09:45:19 +0000239 "enter_" + upgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000240 "enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
241 "enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
mpagenko15ff4a52021-03-02 10:09:20 +0000242 "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000243 "enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
244 "enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
245 },
246 )
247 if instFsm.pAdaptFsm.pFsm == nil {
248 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
249 "device-id": instFsm.deviceID})
250 return nil
251 }
252
253 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
254 return instFsm
255}
256
257//SetDownloadParams configures the needed parameters for a specific download to the ONU
mpagenkoc26d4c02021-05-06 14:27:57 +0000258// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000259func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
260 apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
mpagenko80622a52021-02-09 16:53:23 +0000261 pBaseFsm := oFsm.pAdaptFsm.pFsm
262 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000263 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000264 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
265 "device-id": oFsm.deviceID, "image-description": apImageDsc})
mpagenko15ff4a52021-03-02 10:09:20 +0000266 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000267 oFsm.pImageDsc = apImageDsc
268 oFsm.pDownloadManager = apDownloadManager
Holger Hildebrandtac1e0592021-06-03 15:16:49 +0000269 oFsm.activateImage = true
270 oFsm.commitImage = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000271 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000272
273 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000274 // let the upgrade FSM proceed to PreparingDL
mpagenko80622a52021-02-09 16:53:23 +0000275 _ = aPBaseFsm.Event(upgradeEvPrepareSwDownload)
276 }(pBaseFsm)
277 return nil
278 }
279 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
280 "device-id": oFsm.deviceID})
281 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
282}
283
mpagenkoc26d4c02021-05-06 14:27:57 +0000284//SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
285// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
286// called from 'new' API Download_onu_image
287func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
288 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *fileDownloadManager,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000289 aImageIdentifier string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000290 oFsm.mutexUpgradeParams.Lock()
291 var pBaseFsm *fsm.FSM = nil
292 if oFsm.pAdaptFsm != nil {
293 pBaseFsm = oFsm.pAdaptFsm.pFsm
294 }
295 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
296 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
297 "device-id": oFsm.deviceID, "image-description": apImageRequest})
298 oFsm.useAPIVersion43 = true
299 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
300 oFsm.pFileManager = apDownloadManager
301 oFsm.imageIdentifier = aImageIdentifier
302 oFsm.imageVersion = apImageRequest.Image.Version
303 oFsm.activateImage = apImageRequest.ActivateOnSuccess
304 oFsm.commitImage = apImageRequest.CommitOnSuccess
mpagenkoc26d4c02021-05-06 14:27:57 +0000305 //TODO: currently straightforward options activate and commit are expected to be set and (unconditionally) done
306 // for separate handling of these options the FSM must accordingly branch from the concerned states - later
307 oFsm.mutexUpgradeParams.Unlock()
308 _ = pBaseFsm.Event(upgradeEvAdapterDownload) //no need to call the FSM event in background here
309 return nil
310 }
311 oFsm.mutexUpgradeParams.Unlock()
312 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
313 "device-id": oFsm.deviceID})
314 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
315}
316
317//SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
318// called from 'new' API Activate_onu_image
319func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
320 aImageIdentifier string, aCommit bool) error {
321 oFsm.mutexUpgradeParams.Lock()
322 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
323 // (as long as the Imageidentifier is correct)
324 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
325 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
326 if aImageIdentifier != oFsm.imageIdentifier {
327 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
328 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
329 oFsm.mutexUpgradeParams.Unlock()
330 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
331 oFsm.deviceID))
332 }
333 oFsm.activateImage = true
334 oFsm.commitImage = aCommit
mpagenkoc26d4c02021-05-06 14:27:57 +0000335 var pBaseFsm *fsm.FSM = nil
336 if oFsm.pAdaptFsm != nil {
337 pBaseFsm = oFsm.pAdaptFsm.pFsm
338 }
339 if pBaseFsm != nil {
340 if pBaseFsm.Is(upgradeStWaitForActivate) {
mpagenko38662d02021-08-11 09:45:19 +0000341 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
342 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000343 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
344 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenko38662d02021-08-11 09:45:19 +0000345 } else {
346 oFsm.mutexUpgradeParams.Unlock()
347 logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
348 "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000349 }
350 return nil
351 }
352 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
353 "device-id": oFsm.deviceID})
354 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
355}
356
357//SetActivationParamsStart starts upgrade processing with immediate activation
358// called from 'new' API Activate_onu_image
359func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
360 oFsm.mutexUpgradeParams.Lock()
361 var pBaseFsm *fsm.FSM = nil
362 if oFsm.pAdaptFsm != nil {
363 pBaseFsm = oFsm.pAdaptFsm.pFsm
364 }
365 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
366 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
367 "device-id": oFsm.deviceID, "image-version": aImageVersion})
368 oFsm.useAPIVersion43 = true
369 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
370 oFsm.imageVersion = aImageVersion
371 oFsm.activateImage = true
372 oFsm.commitImage = aCommit
mpagenko38662d02021-08-11 09:45:19 +0000373 // indicate start of the upgrade activity
374 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
375 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE //as simply applied for inactive image
mpagenkoc26d4c02021-05-06 14:27:57 +0000376 oFsm.mutexUpgradeParams.Unlock()
377 //directly request the FSM to activate the image
378 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
379 return nil
380 }
381 oFsm.mutexUpgradeParams.Unlock()
382 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
383 "device-id": oFsm.deviceID})
384 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
385}
386
387//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
388// called from 'new' API Commit_onu_image
mpagenko38662d02021-08-11 09:45:19 +0000389func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
390 aImageIdentifier string, aImageVersion string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000391 oFsm.mutexUpgradeParams.Lock()
392 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
393 // (as long as the Imageidentifier is correct)
394 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
395 "device-id": oFsm.deviceID, "image-id": aImageIdentifier})
mpagenko38662d02021-08-11 09:45:19 +0000396 if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000397 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
mpagenko38662d02021-08-11 09:45:19 +0000398 "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
399 "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
mpagenkoc26d4c02021-05-06 14:27:57 +0000400 oFsm.mutexUpgradeParams.Unlock()
401 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
402 oFsm.deviceID))
403 }
404 oFsm.commitImage = true
mpagenko38662d02021-08-11 09:45:19 +0000405 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
mpagenkoc26d4c02021-05-06 14:27:57 +0000406 oFsm.mutexUpgradeParams.Unlock()
407 var pBaseFsm *fsm.FSM = nil
408 if oFsm.pAdaptFsm != nil {
409 pBaseFsm = oFsm.pAdaptFsm.pFsm
410 }
411 if pBaseFsm != nil {
mpagenko183647c2021-06-08 15:25:04 +0000412 //let the FSM decide if it is ready to process the event
413 logger.Debugw(ctx, "OnuUpgradeFsm requesting commit",
414 log.Fields{"device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
415 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000416 return nil
417 }
mpagenko38662d02021-08-11 09:45:19 +0000418 //should never occur
mpagenkoc26d4c02021-05-06 14:27:57 +0000419 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
420 "device-id": oFsm.deviceID})
421 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
422}
423
424//SetCommitmentParamsStart starts upgrade processing with immediate commitment
425// called from 'new' API Commit_onu_image
426func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
427 oFsm.mutexUpgradeParams.Lock()
428 var pBaseFsm *fsm.FSM = nil
429 if oFsm.pAdaptFsm != nil {
430 pBaseFsm = oFsm.pAdaptFsm.pFsm
431 }
432 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
433 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
434 "device-id": oFsm.deviceID, "image-version": aImageVersion})
435 oFsm.useAPIVersion43 = true
436 oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
437 oFsm.imageVersion = aImageVersion
438 oFsm.commitImage = true
mpagenko38662d02021-08-11 09:45:19 +0000439 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
440 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE //as simply applied for active image
mpagenkoc26d4c02021-05-06 14:27:57 +0000441 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +0000442 //directly request the FSM to commit the image
mpagenkoc26d4c02021-05-06 14:27:57 +0000443 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
444 return nil
445 }
446 oFsm.mutexUpgradeParams.Unlock()
447 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
448 "device-id": oFsm.deviceID})
449 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
450}
451
mpagenko1f8e8822021-06-25 14:10:21 +0000452//GetCommitFlag delivers the commit flag that was configured here
453func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
454 oFsm.mutexUpgradeParams.RLock()
455 defer oFsm.mutexUpgradeParams.RUnlock()
456 return oFsm.commitImage
457}
458
mpagenko38662d02021-08-11 09:45:19 +0000459//GetImageStates delivers the download/image states as per device proto buf definition
mpagenkoaa3afe92021-05-21 16:20:58 +0000460func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
mpagenko38662d02021-08-11 09:45:19 +0000461 aImageIdentifier string, aVersion string) *voltha.ImageState {
mpagenkoaa3afe92021-05-21 16:20:58 +0000462 pImageState := &voltha.ImageState{}
mpagenko38662d02021-08-11 09:45:19 +0000463 pImageState.Version = aVersion //version as requested
mpagenkoaa3afe92021-05-21 16:20:58 +0000464 // check if the request refers to some active image/version of the processing
465 oFsm.mutexUpgradeParams.RLock()
466 if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
467 pImageState.DownloadState = oFsm.volthaDownloadState
468 pImageState.Reason = oFsm.volthaDownloadReason
469 pImageState.ImageState = oFsm.volthaImageState
470 } else {
471 pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
472 pImageState.Reason = voltha.ImageState_NO_ERROR
473 pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
474 }
475 oFsm.mutexUpgradeParams.RUnlock()
mpagenko38662d02021-08-11 09:45:19 +0000476 return pImageState
mpagenkoaa3afe92021-05-21 16:20:58 +0000477}
478
mpagenko38662d02021-08-11 09:45:19 +0000479//GetSpecificImageState delivers ImageState of the download/image states as per device proto buf definition
480func (oFsm *OnuUpgradeFsm) GetSpecificImageState(ctx context.Context) voltha.ImageState_ImageActivationState {
481 oFsm.mutexUpgradeParams.RLock()
482 imageState := oFsm.volthaImageState
483 oFsm.mutexUpgradeParams.RUnlock()
484 return imageState
485}
486
487//SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
488func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
mpagenko183647c2021-06-08 15:25:04 +0000489 oFsm.mutexUpgradeParams.Lock()
490 defer oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +0000491 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
492 if !oFsm.commitImage {
493 //if commit is not additionally set, regard the upgrade activity as successful
494 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED //better choice would be 'UpgradeState=Succeeded'
495 }
496}
497
498//GetImageVersion delivers image-version of the running upgrade
499func (oFsm *OnuUpgradeFsm) GetImageVersion(ctx context.Context) string {
500 oFsm.mutexUpgradeParams.RLock()
501 imageVersion := oFsm.imageVersion
502 oFsm.mutexUpgradeParams.RUnlock()
503 return imageVersion
mpagenko183647c2021-06-08 15:25:04 +0000504}
505
mpagenkoc26d4c02021-05-06 14:27:57 +0000506//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko38662d02021-08-11 09:45:19 +0000507func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
508 aReason voltha.ImageState_ImageFailureReason) {
509 oFsm.mutexAbortRequest.Lock()
510 oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
511 oFsm.mutexAbortRequest.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000512 //mutex protection is required for possible concurrent access to FSM members
513 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
514 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
515 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
516 if oFsm.isWaitingForAdapterDlResponse {
517 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
518 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
519 oFsm.chAdapterDlReady <- false
520 } else {
521 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
522 }
523 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
524
525 // 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 +0000526 // specific here: See definition of state changes: some states are excluded from reset for possible later commit
mpagenkoc26d4c02021-05-06 14:27:57 +0000527 pAdaptFsm := oFsm.pAdaptFsm
528 if pAdaptFsm != nil {
529 // calling FSM events in background to avoid blocking of the caller
530 go func(aPAFsm *AdapterFsm) {
531 if aPAFsm.pFsm != nil {
532 if aPAFsm.pFsm.Is(upgradeStWaitEndDL) {
mpagenko38662d02021-08-11 09:45:19 +0000533 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
mpagenkoc26d4c02021-05-06 14:27:57 +0000534 }
mpagenko38662d02021-08-11 09:45:19 +0000535 // in case of state-conditional request the
536
537 var err error
538 if abCompleteAbort {
539 oFsm.mutexUpgradeParams.Lock()
540 //any previous lingering conditional cancelRequest is superseded by this abortion
541 oFsm.conditionalCancelRequested = false
542 if aReason == voltha.ImageState_CANCELLED_ON_REQUEST {
543 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
544 } else {
545 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
546 }
547 oFsm.volthaDownloadReason = aReason
548 oFsm.mutexUpgradeParams.Unlock()
549 err = aPAFsm.pFsm.Event(upgradeEvAbort) //as unconditional default FSM cancellation
550 } else {
551 //at conditional request the image states are set when reaching the reset state
552 oFsm.conditionalCancelRequested = true
553 err = aPAFsm.pFsm.Event(upgradeEvReset) //as state-conditional default FSM cleanup
554 }
555 if err != nil {
556 //error return is expected in case of conditional request and no state transition
557 logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
558 "device-id": oFsm.deviceID, "error": err})
559 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000560 } //else the FSM seems already to be in some released state
561 }(pAdaptFsm)
562 }
563}
564
mpagenko80622a52021-02-09 16:53:23 +0000565func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
566 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
567 "device-id": oFsm.deviceID})
568
569 // start go routine for processing of LockState messages
570 go oFsm.processOmciUpgradeMessages(ctx)
571}
572
mpagenkoc26d4c02021-05-06 14:27:57 +0000573//enterWaitingAdapterDL state can only be reached with useAPIVersion43
574func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
575 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
576 "device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +0000577 syncChannel := make(chan struct{})
578 go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
579 //block until the wait routine is really blocked on chAdapterDlReady
580 <-syncChannel
mpagenkoc26d4c02021-05-06 14:27:57 +0000581 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
582}
583
mpagenko80622a52021-02-09 16:53:23 +0000584func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
585 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
586 "device-id": oFsm.deviceID})
587
mpagenkoc26d4c02021-05-06 14:27:57 +0000588 var fileLen int64
589 var err error
mpagenkoaa3afe92021-05-21 16:20:58 +0000590 oFsm.mutexUpgradeParams.Lock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000591 if oFsm.useAPIVersion43 {
592 //with the new API structure download to adapter is implicit and we have to wait until the image is available
593 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
594 } else {
595 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
596 }
mpagenko80622a52021-02-09 16:53:23 +0000597 if err != nil || fileLen > int64(cMaxUint32) {
mpagenko38662d02021-08-11 09:45:19 +0000598 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
599 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //Something like 'LOCAL_FILE_ERROR' would be better (proto)
600 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
mpagenkoaa3afe92021-05-21 16:20:58 +0000601 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000602 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
603 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
604 pBaseFsm := oFsm.pAdaptFsm
605 // Can't call FSM Event directly, decoupling it
606 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000607 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000608 }(pBaseFsm)
609 return
610 }
611
mpagenkoc26d4c02021-05-06 14:27:57 +0000612 //copy file content to buffer
mpagenko80622a52021-02-09 16:53:23 +0000613 oFsm.imageBuffer = make([]byte, fileLen)
mpagenkoc26d4c02021-05-06 14:27:57 +0000614 if oFsm.useAPIVersion43 {
615 oFsm.imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
616 } else {
617 oFsm.imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
618 }
mpagenko80622a52021-02-09 16:53:23 +0000619 if err != nil {
mpagenko38662d02021-08-11 09:45:19 +0000620 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
621 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //Something like 'LOCAL_FILE_ERROR' would be better (proto)
622 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
mpagenkoaa3afe92021-05-21 16:20:58 +0000623 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000624 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
625 "device-id": oFsm.deviceID, "error": err})
626 pBaseFsm := oFsm.pAdaptFsm
627 // Can't call FSM Event directly, decoupling it
628 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000629 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000630 }(pBaseFsm)
631 return
632 }
633
634 oFsm.noOfSections = uint32(fileLen / cOmciDownloadSectionSize)
635 if fileLen%cOmciDownloadSectionSize > 0 {
mpagenkoc26d4c02021-05-06 14:27:57 +0000636 bufferPadding := make([]byte, cOmciDownloadSectionSize-uint32((fileLen)%cOmciDownloadSectionSize))
mpagenko80622a52021-02-09 16:53:23 +0000637 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
mpagenkoc26d4c02021-05-06 14:27:57 +0000638 oFsm.imageBuffer = append(oFsm.imageBuffer[:(fileLen)], bufferPadding...)
mpagenko80622a52021-02-09 16:53:23 +0000639 oFsm.noOfSections++
640 }
641 oFsm.origImageLength = uint32(fileLen)
642 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000643 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
644 "MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
645 "ImageSize": oFsm.imageLength, "original file size": fileLen})
646 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
mpagenkoaa3afe92021-05-21 16:20:58 +0000647
648 oFsm.mutexUpgradeParams.Unlock()
649 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
650
Girish Gowdra0b235842021-03-09 13:06:46 -0800651 err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000652 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
653 if err != nil {
654 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
655 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000656 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000657 return
658 }
659}
660
661func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
662 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
663 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
664
665 var windowAckRequest uint8 = 0
666 var bufferStartOffset uint32
667 var bufferEndOffset uint32
668 var downloadSection []byte
669 framePrint := false //default no printing of downloadSection frames
mpagenkoaa3afe92021-05-21 16:20:58 +0000670 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000671 if oFsm.nextDownloadSectionsAbsolute == 0 {
672 //debug print of first section frame
673 framePrint = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000674 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
mpagenko80622a52021-02-09 16:53:23 +0000675 }
676
677 for {
mpagenko38662d02021-08-11 09:45:19 +0000678 oFsm.mutexAbortRequest.RLock()
679 // this way out of the section download loop on abort request
680 if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
681 if oFsm.abortRequested == voltha.ImageState_CANCELLED_ON_REQUEST {
682 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
683 } else {
684 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
685 }
686 oFsm.volthaDownloadReason = oFsm.abortRequested
687 oFsm.mutexAbortRequest.RUnlock()
688 oFsm.mutexUpgradeParams.Unlock()
689 pBaseFsm := oFsm.pAdaptFsm
690 // Can't call FSM Event directly, decoupling it
691 go func(a_pAFsm *AdapterFsm) {
692 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
693 }(pBaseFsm)
694 return
695 }
696 oFsm.mutexAbortRequest.RUnlock()
697
mpagenko80622a52021-02-09 16:53:23 +0000698 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
699 bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
700 logger.Debugw(ctx, "DlSection values are", log.Fields{
701 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
702 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
703 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
704 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
705 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
706 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
707 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
mpagenko38662d02021-08-11 09:45:19 +0000708 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
709 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //Something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000710 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000711 //logical error -- reset the FSM
712 pBaseFsm := oFsm.pAdaptFsm
713 // Can't call FSM Event directly, decoupling it
714 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000715 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000716 }(pBaseFsm)
717 return
718 }
719 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
720 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
721 windowAckRequest = 1
722 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
723 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
724 }
725 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
726 windowAckRequest = 1
727 framePrint = true //debug print of last frame
mpagenko15ff4a52021-03-02 10:09:20 +0000728 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
729 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000730 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
731 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000732 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 -0800733 err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000734 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
735 if err != nil {
736 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000737 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000738 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000739 return
740 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000741 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000742 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
743 if windowAckRequest == 1 {
744 pBaseFsm := oFsm.pAdaptFsm
745 // Can't call FSM Event directly, decoupling it
mpagenkoaa3afe92021-05-21 16:20:58 +0000746 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000747 go func(a_pAFsm *AdapterFsm) {
748 _ = a_pAFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
749 }(pBaseFsm)
750 return
751 }
752 framePrint = false //for the next Section frame (if wanted, can be enabled in logic before sendXXX())
753 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000754 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000755 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenkoaa3afe92021-05-21 16:20:58 +0000756 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko59498c12021-03-18 14:15:15 +0000757 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenkoaa3afe92021-05-21 16:20:58 +0000758 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000759 }
760 }
761}
762
763func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
764 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
765 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
766}
767
768func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000769 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000770 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
mpagenko80622a52021-02-09 16:53:23 +0000771
mpagenkoaa3afe92021-05-21 16:20:58 +0000772 oFsm.mutexUpgradeParams.RLock()
mpagenko80622a52021-02-09 16:53:23 +0000773 if oFsm.delayEndSwDl {
mpagenkoaa3afe92021-05-21 16:20:58 +0000774 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000775 //give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
776 // should not be set in case this state is used for real download abort (not yet implemented)
777 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoaa3afe92021-05-21 16:20:58 +0000778 } else {
779 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000780 }
781
mpagenko59498c12021-03-18 14:15:15 +0000782 pBaseFsm := oFsm.pAdaptFsm
783 if pBaseFsm == nil {
mpagenko38662d02021-08-11 09:45:19 +0000784 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
785 oFsm.mutexUpgradeParams.Lock()
786 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
787 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
788 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000789 // Can't call FSM Event directly, decoupling it
790 go func(a_pAFsm *AdapterFsm) {
791 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
792 }(pBaseFsm)
793 return
794 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800795 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko59498c12021-03-18 14:15:15 +0000796 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.origImageLength, oFsm.imageCRC)
mpagenko80622a52021-02-09 16:53:23 +0000797 if err != nil {
798 logger.Errorw(ctx, "EndSwDl abort: can't send section", log.Fields{
799 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000800 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000801 return
802 }
mpagenko59498c12021-03-18 14:15:15 +0000803 // go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
804 // Can't call FSM Event directly, decoupling it
805 go func(a_pAFsm *AdapterFsm) {
806 _ = a_pAFsm.pFsm.Event(upgradeEvWaitEndDownload)
807 }(pBaseFsm)
808}
809
810func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
811 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
812 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
813 if oFsm.waitCountEndSwDl == 0 {
814 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
815 "device-id": oFsm.deviceID})
816 pBaseFsm := oFsm.pAdaptFsm
817 if pBaseFsm == nil {
818 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
819 "device-id": oFsm.deviceID})
820 return
821 }
mpagenko38662d02021-08-11 09:45:19 +0000822 oFsm.mutexUpgradeParams.Lock()
823 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
824 oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //Something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
825 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000826 go func(a_pAFsm *AdapterFsm) {
827 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
828 }(pBaseFsm)
829 return
830 }
831
832 oFsm.waitCountEndSwDl--
833 select {
834 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
835 pBaseFsm := oFsm.pAdaptFsm
836 if pBaseFsm == nil {
837 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
838 "device-id": oFsm.deviceID})
839 //FSM may be reset already from somewhere else, nothing we can do here anymore
840 return
841 }
842 //retry End SW DL
mpagenkoaa3afe92021-05-21 16:20:58 +0000843 oFsm.mutexUpgradeParams.Lock()
mpagenko59498c12021-03-18 14:15:15 +0000844 oFsm.delayEndSwDl = false //no more extra delay for the request
mpagenkoaa3afe92021-05-21 16:20:58 +0000845 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000846 go func(a_pAFsm *AdapterFsm) {
847 _ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
848 }(pBaseFsm)
849 return
850 case success := <-oFsm.chReceiveExpectedResponse:
851 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
852 pBaseFsm := oFsm.pAdaptFsm
853 if pBaseFsm == nil {
854 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
855 "device-id": oFsm.deviceID})
856 //FSM may be reset already from somewhere else, nothing we can do here anymore
857 return
858 }
859 if success {
860 //answer received with ready indication
mpagenko38662d02021-08-11 09:45:19 +0000861 //useAPIVersion43 may not conflict in concurrency in this state function
862 if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
mpagenkoc26d4c02021-05-06 14:27:57 +0000863 go func(a_pAFsm *AdapterFsm) {
mpagenko38662d02021-08-11 09:45:19 +0000864 _ = a_pAFsm.pFsm.Event(upgradeEvCheckImageName)
mpagenkoc26d4c02021-05-06 14:27:57 +0000865 }(pBaseFsm)
mpagenko38662d02021-08-11 09:45:19 +0000866 } else { // elder API usage does not support image version check -immediately consider download as successful
867 if oFsm.activateImage {
868 //immediate activation requested
869 go func(a_pAFsm *AdapterFsm) {
870 _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
871 }(pBaseFsm)
872 } else {
873 //have to wait on explicit activation request
874 go func(a_pAFsm *AdapterFsm) {
875 _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
876 }(pBaseFsm)
877 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000878 }
mpagenko59498c12021-03-18 14:15:15 +0000879 return
880 }
881 //timer was aborted
mpagenko38662d02021-08-11 09:45:19 +0000882 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko59498c12021-03-18 14:15:15 +0000883 return
884 }
mpagenko80622a52021-02-09 16:53:23 +0000885}
886
mpagenko38662d02021-08-11 09:45:19 +0000887func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
888 logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
889 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
890 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
891 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
892 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
893 false, oFsm.pAdaptFsm.commChan)
894 if err != nil {
895 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
896 log.Fields{"device-id": oFsm.deviceID, "Error": err})
897 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
898 return
899 }
900 oFsm.pLastTxMeInstance = meInstance
901}
902
mpagenko80622a52021-02-09 16:53:23 +0000903func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
904 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
905 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
906
Girish Gowdra0b235842021-03-09 13:06:46 -0800907 err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000908 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
909 if err != nil {
910 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
911 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000912 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +0000913 return
914 }
mpagenko38662d02021-08-11 09:45:19 +0000915 oFsm.mutexUpgradeParams.Lock()
916 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
917 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000918}
919
920func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +0000921 logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
922 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
923 //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
924 // (which is a bit problematic as the ONU might already be in committed state,
925 // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
926 if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
mpagenkoaa3afe92021-05-21 16:20:58 +0000927 oFsm.mutexUpgradeParams.Lock()
mpagenko38662d02021-08-11 09:45:19 +0000928 if activeImageID == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +0000929 inactiveImageID := oFsm.inactiveImageMeID
mpagenko15ff4a52021-03-02 10:09:20 +0000930 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
mpagenkoaa3afe92021-05-21 16:20:58 +0000931 "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
932 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
933 oFsm.mutexUpgradeParams.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800934 err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenkoaa3afe92021-05-21 16:20:58 +0000935 oFsm.pAdaptFsm.commChan, inactiveImageID) //more efficient activeImageID with above check
mpagenko15ff4a52021-03-02 10:09:20 +0000936 if err != nil {
937 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
938 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000939 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +0000940 return
941 }
942 return
943 }
mpagenko38662d02021-08-11 09:45:19 +0000944 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000945 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
946 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
mpagenko38662d02021-08-11 09:45:19 +0000947 } else {
948 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
949 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000950 }
mpagenko38662d02021-08-11 09:45:19 +0000951 oFsm.mutexUpgradeParams.Lock()
952 oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
953 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
954 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
955 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
956 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000957 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
958 pBaseFsm := oFsm.pAdaptFsm
959 // Can't call FSM Event directly, decoupling it
960 go func(a_pAFsm *AdapterFsm) {
961 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
962 }(pBaseFsm)
963}
964
965func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +0000966 logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000967 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
mpagenko15ff4a52021-03-02 10:09:20 +0000968 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
ozgecanetsiab36ed572021-04-01 10:38:48 +0300969 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
Girish Gowdra0b235842021-03-09 13:06:46 -0800970 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300971 if err != nil {
972 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
973 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko38662d02021-08-11 09:45:19 +0000974 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300975 return
976 }
mpagenko15ff4a52021-03-02 10:09:20 +0000977 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +0000978}
979
980func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
981 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
982
mpagenko38662d02021-08-11 09:45:19 +0000983 // if the reset was conditionally requested
984 if oFsm.conditionalCancelRequested {
985 oFsm.mutexUpgradeParams.Lock()
986 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
987 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
988 oFsm.mutexUpgradeParams.Unlock()
989 }
990
mpagenkoc26d4c02021-05-06 14:27:57 +0000991 // in case the download-to-ONU timer is still running - cancel it
992 oFsm.mutexIsAwaitingOnuDlResponse.RLock()
993 if oFsm.isWaitingForOnuDlResponse {
994 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
995 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
996 oFsm.chOnuDlReady <- false
997 } else {
998 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
999 }
1000
mpagenko80622a52021-02-09 16:53:23 +00001001 pConfigupgradeStateAFsm := oFsm.pAdaptFsm
1002 if pConfigupgradeStateAFsm != nil {
1003 // abort running message processing
1004 fsmAbortMsg := Message{
1005 Type: TestMsg,
1006 Data: TestMessage{
1007 TestMessageVal: AbortMessageProcessing,
1008 },
1009 }
1010 pConfigupgradeStateAFsm.commChan <- fsmAbortMsg
1011
1012 //try to restart the FSM to 'disabled'
1013 // Can't call FSM Event directly, decoupling it
1014 go func(a_pAFsm *AdapterFsm) {
1015 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1016 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1017 }
1018 }(pConfigupgradeStateAFsm)
1019 }
1020}
1021
1022func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1023 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001024 // 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 +00001025 if oFsm.pDeviceHandler != nil {
1026 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenko38662d02021-08-11 09:45:19 +00001027 pLastUpgradeImageState := &voltha.ImageState{
1028 Version: oFsm.imageVersion,
1029 DownloadState: oFsm.volthaDownloadState,
1030 Reason: oFsm.volthaDownloadReason,
1031 ImageState: oFsm.volthaImageState,
1032 }
1033 go oFsm.pDeviceHandler.removeOnuUpgradeFsm(ctx, pLastUpgradeImageState)
mpagenko80622a52021-02-09 16:53:23 +00001034 }
1035}
1036
1037func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
1038 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
1039loop:
1040 for {
1041 // case <-ctx.Done():
1042 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
1043 // break loop
1044 message, ok := <-oFsm.pAdaptFsm.commChan
1045 if !ok {
1046 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
1047 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko38662d02021-08-11 09:45:19 +00001048 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +00001049 break loop
1050 }
1051 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
1052
1053 switch message.Type {
1054 case TestMsg:
1055 msg, _ := message.Data.(TestMessage)
1056 if msg.TestMessageVal == AbortMessageProcessing {
1057 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
1058 break loop
1059 }
1060 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
1061 case OMCI:
1062 msg, _ := message.Data.(OmciMessage)
1063 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
1064 default:
1065 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
1066 "message.Type": message.Type})
1067 }
1068 }
1069 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
1070}
1071
1072//nolint: gocyclo
1073func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg OmciMessage) {
1074 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
1075 "msgType": msg.OmciMsg.MessageType})
1076
1077 switch msg.OmciMsg.MessageType {
1078 case omci.StartSoftwareDownloadResponseType:
1079 {
1080 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
1081 if msgLayer == nil {
1082 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
1083 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001084 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001085 return
1086 }
1087 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
1088 if !msgOk {
1089 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
1090 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001091 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001092 return
1093 }
1094 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
1095 "device-id": oFsm.deviceID, "data-fields": msgObj})
1096 if msgObj.Result != me.Success {
1097 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
1098 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001099 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001100 return
1101 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001102
1103 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001104 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1105 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1106 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
1107 // also response WindowSize = 0 is a valid number for used Window size 1
1108 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
1109 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
1110 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
1111 }
1112 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
1113 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
1114 oFsm.noOfWindows++
1115 }
1116 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
1117 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
1118 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
1119 oFsm.nextDownloadSectionsAbsolute = 0
1120 oFsm.nextDownloadSectionsWindow = 0
1121 oFsm.nextDownloadWindow = 0
1122
mpagenkoaa3afe92021-05-21 16:20:58 +00001123 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001124 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
1125 return
1126 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001127 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001128 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1129 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001130 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001131 return
1132 } //StartSoftwareDownloadResponseType
1133 case omci.DownloadSectionResponseType:
1134 {
mpagenko80622a52021-02-09 16:53:23 +00001135 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
1136 if msgLayer == nil {
1137 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
1138 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
mpagenko38662d02021-08-11 09:45:19 +00001139 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001140 return
1141 }
1142 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
1143 if !msgOk {
1144 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
1145 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001146 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001147 return
1148 }
1149 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
1150 "device-id": oFsm.deviceID, "data-fields": msgObj})
1151 if msgObj.Result != me.Success {
1152 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
1153 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001154 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001155 return
1156 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001157 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001158 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1159 sectionNumber := msgObj.SectionNumber
mpagenko15ff4a52021-03-02 10:09:20 +00001160 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
1161 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +00001162
mpagenko15ff4a52021-03-02 10:09:20 +00001163 oFsm.nextDownloadWindow++
1164 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
1165 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
mpagenko02cf1b22021-03-12 17:30:30 +00001166 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
mpagenko15ff4a52021-03-02 10:09:20 +00001167 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
1168 "expected section": oFsm.omciDownloadWindowSizeLast})
mpagenkoaa3afe92021-05-21 16:20:58 +00001169 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001170 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko15ff4a52021-03-02 10:09:20 +00001171 return
1172 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001173 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
1174 //CRC computation for all data bytes of the file
1175 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
1176 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
1177 var byteSlice []byte = make([]byte, 4)
1178 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
1179 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
mpagenkoaa3afe92021-05-21 16:20:58 +00001180 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001181 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
1182 return
1183 }
1184 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
1185 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
mpagenko02cf1b22021-03-12 17:30:30 +00001186 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
1187 "expected section": oFsm.omciDownloadWindowSizeLimit})
mpagenkoaa3afe92021-05-21 16:20:58 +00001188 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001189 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko15ff4a52021-03-02 10:09:20 +00001190 return
1191 }
1192 oFsm.nextDownloadSectionsWindow = 0
mpagenkoaa3afe92021-05-21 16:20:58 +00001193 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001194 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
mpagenko80622a52021-02-09 16:53:23 +00001195 return
1196 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001197 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001198 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1199 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001200 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001201 return
mpagenko80622a52021-02-09 16:53:23 +00001202 } //DownloadSectionResponseType
1203 case omci.EndSoftwareDownloadResponseType:
1204 {
1205 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1206 if msgLayer == nil {
1207 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1208 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001209 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001210 return
1211 }
1212 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1213 if !msgOk {
1214 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1215 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001216 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001217 return
1218 }
1219 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1220 "device-id": oFsm.deviceID, "data-fields": msgObj})
1221 if msgObj.Result != me.Success {
mpagenko59498c12021-03-18 14:15:15 +00001222 if msgObj.Result == me.DeviceBusy {
1223 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1224 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1225 "device-id": oFsm.deviceID})
1226 return
1227 }
mpagenko80622a52021-02-09 16:53:23 +00001228 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
1229 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001230 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001231 return
1232 }
mpagenko183647c2021-06-08 15:25:04 +00001233 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001234 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko38662d02021-08-11 09:45:19 +00001235 //EndSwDownloadSuccess is used to indicate 'DOWNLOAD_SUCCEEDED'
mpagenko183647c2021-06-08 15:25:04 +00001236 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
mpagenko38662d02021-08-11 09:45:19 +00001237 if !oFsm.useAPIVersion43 {
1238 //in the older API version the image version check was not possible
1239 // - assume new loaded image as valid-inactive immediately
1240 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1241 oFsm.mutexUpgradeParams.Unlock()
1242 oFsm.mutexIsAwaitingOnuDlResponse.RLock()
1243 if oFsm.isWaitingForOnuDlResponse {
1244 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1245 //use non-blocking channel to indicate that the download to ONU was successful
1246 select {
1247 case oFsm.chOnuDlReady <- true:
1248 default:
1249 }
1250 } else {
1251 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1252 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001253 } else {
mpagenko38662d02021-08-11 09:45:19 +00001254 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001255 }
mpagenko38662d02021-08-11 09:45:19 +00001256 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1257 //use non-blocking channel to let the FSM proceed from the waitState
1258 select {
1259 case oFsm.chReceiveExpectedResponse <- true:
1260 default:
1261 }
mpagenko80622a52021-02-09 16:53:23 +00001262 return
1263 }
mpagenko183647c2021-06-08 15:25:04 +00001264 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001265 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1266 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001267 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001268 return
1269 } //EndSoftwareDownloadResponseType
1270 case omci.ActivateSoftwareResponseType:
1271 {
1272 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1273 if msgLayer == nil {
1274 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1275 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001276 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001277 return
1278 }
1279 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1280 if !msgOk {
1281 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1282 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001283 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001284 return
1285 }
1286 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1287 "device-id": oFsm.deviceID, "data-fields": msgObj})
1288 if msgObj.Result != me.Success {
1289 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1290 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001291 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001292 return
1293 }
mpagenko183647c2021-06-08 15:25:04 +00001294 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001295 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko38662d02021-08-11 09:45:19 +00001296 // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
mpagenko183647c2021-06-08 15:25:04 +00001297 oFsm.mutexUpgradeParams.Unlock()
1298 logger.Infow(ctx, "Expected ActivateSwResponse received",
1299 log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
1300 if oFsm.commitImage {
1301 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
1302 } else {
1303 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvActivationDone) // let the FSM wait for external commit request
1304 }
mpagenko80622a52021-02-09 16:53:23 +00001305 return
1306 }
mpagenko183647c2021-06-08 15:25:04 +00001307 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001308 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1309 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001310 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001311 return
1312 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001313 case omci.CommitSoftwareResponseType:
1314 {
1315 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1316 if msgLayer == nil {
1317 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1318 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001319 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001320 return
1321 }
1322 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1323 if !msgOk {
1324 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1325 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001326 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001327 return
1328 }
mpagenkobf67a092021-03-17 09:52:28 +00001329 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001330 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1331 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001332 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001333 return
mpagenkobf67a092021-03-17 09:52:28 +00001334 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001335 oFsm.mutexUpgradeParams.RLock()
mpagenko15ff4a52021-03-02 10:09:20 +00001336 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001337 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001338 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1339 //verifying committed image
1340 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
1341 return
1342 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001343 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001344 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1345 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001346 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001347 return
1348 } //CommitSoftwareResponseType
1349 case omci.GetResponseType:
1350 {
1351 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1352 if msgLayer == nil {
1353 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1354 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001355 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001356 return
1357 }
1358 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1359 if !msgOk {
1360 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1361 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001362 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001363 return
1364 }
1365 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1366 "device-id": oFsm.deviceID, "data-fields": msgObj})
1367 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1368 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1369 if msgObj.Result != me.Success {
1370 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1371 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001372 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001373 return
1374 }
1375 } else {
1376 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1377 log.Fields{"device-id": oFsm.deviceID})
1378 return
1379 }
1380
1381 meAttributes := msgObj.Attributes
1382 imageIsCommitted := meAttributes["IsCommitted"].(uint8)
1383 imageIsActive := meAttributes["IsActive"].(uint8)
Holger Hildebrandtfb402a62021-05-26 14:40:49 +00001384 imageVersion := TrimStringFromMeOctet(meAttributes["Version"])
mpagenko02cf1b22021-03-12 17:30:30 +00001385 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
mpagenko15ff4a52021-03-02 10:09:20 +00001386 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1387 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
mpagenkoaa3afe92021-05-21 16:20:58 +00001388
mpagenko38662d02021-08-11 09:45:19 +00001389 if oFsm.pAdaptFsm.pFsm.Current() == upgradeStCheckImageName {
1390 //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
1391 oFsm.mutexUpgradeParams.Lock()
1392 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsInactive &&
1393 imageIsCommitted == swIsUncommitted {
1394 if imageVersion != oFsm.imageVersion {
1395 //new stored inactive version indicated on OMCI from ONU is not the expected version
1396 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
1397 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1398 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1399 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was downloaded
1400 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1401 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'DOWNLOADED' would be better - proto def
1402 oFsm.mutexUpgradeParams.Unlock()
1403 //stop the running ONU download timer
1404 oFsm.mutexIsAwaitingOnuDlResponse.RLock()
1405 if oFsm.isWaitingForOnuDlResponse {
1406 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1407 //use channel to indicate that the download to ONU was not successful
1408 oFsm.chOnuDlReady <- false
1409 } else {
1410 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1411 }
1412 // TODO!!!: error treatment?
1413 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1414 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1415 return
1416 }
1417 //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
1418 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1419 //store the new inactive version to onuSwImageIndications (to keep them in sync)
1420 oFsm.pDevEntry.modifySwImageInactiveVersion(ctx, oFsm.imageVersion)
1421 //proceed within upgrade FSM
1422 if oFsm.activateImage {
1423 //immediate activation requested
1424 oFsm.mutexUpgradeParams.Unlock()
1425 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
1426 log.Fields{"device-id": oFsm.deviceID})
1427 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRequestActivate)
1428 } else {
1429 //have to wait on explicit activation request
1430 // but a previously requested download activity (without activation) was successful here
1431 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1432 oFsm.mutexUpgradeParams.Unlock()
1433 logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
1434 log.Fields{"device-id": oFsm.deviceID})
1435 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForActivate)
1436 }
1437 oFsm.mutexIsAwaitingOnuDlResponse.RLock()
1438 if oFsm.isWaitingForOnuDlResponse {
1439 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1440 //use channel to indicate that the download to ONU was successful
1441 oFsm.chOnuDlReady <- true
1442 } else {
1443 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1444 }
1445 return
1446 }
1447 //not the expected image/image state
1448 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1449 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1450 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //real image state not known
1451 oFsm.mutexUpgradeParams.Unlock()
1452 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1453 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1454 // TODO!!!: error treatment?
1455 //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
1456 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1457 return
1458 }
1459
1460 //assumed only relevant state here is upgradeStCheckCommitted
mpagenkoaa3afe92021-05-21 16:20:58 +00001461 oFsm.mutexUpgradeParams.Lock()
mpagenko38662d02021-08-11 09:45:19 +00001462 oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
mpagenkoaa3afe92021-05-21 16:20:58 +00001463 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive {
mpagenkoc26d4c02021-05-06 14:27:57 +00001464 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1465 // indicated in the download image version string (version must be part of the image content itself)
1466 // so checking that might be quite unreliable
1467 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1468 // in all the API references, so it can and should be checked here now
1469 if oFsm.useAPIVersion43 {
1470 if imageVersion != oFsm.imageVersion {
1471 //new active version indicated on OMCI from ONU is not the expected version
mpagenko38662d02021-08-11 09:45:19 +00001472 logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
mpagenkoc26d4c02021-05-06 14:27:57 +00001473 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1474 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1475 // TODO!!!: error treatment?
mpagenko38662d02021-08-11 09:45:19 +00001476 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1477 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was committed
1478 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1479 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //expected image not known
1480 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001481 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1482 return
1483 }
1484 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1485 log.Fields{"device-id": oFsm.deviceID})
1486 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001487 if imageIsCommitted == swIsCommitted {
mpagenko38662d02021-08-11 09:45:19 +00001488 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
mpagenkoaa3afe92021-05-21 16:20:58 +00001489 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
mpagenko38662d02021-08-11 09:45:19 +00001490 //store the new commit flag to onuSwImageIndications (to keep them in sync)
1491 oFsm.pDevEntry.modifySwImageActiveCommit(ctx, imageIsCommitted)
mpagenkoaa3afe92021-05-21 16:20:58 +00001492 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001493 //deviceProcStatusUpdate not used anymore,
1494 // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
mpagenkoaa3afe92021-05-21 16:20:58 +00001495 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001496 //releasing the upgrade FSM on success
mpagenko183647c2021-06-08 15:25:04 +00001497 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenkoaa3afe92021-05-21 16:20:58 +00001498 return
1499 }
mpagenko38662d02021-08-11 09:45:19 +00001500 //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
mpagenko15ff4a52021-03-02 10:09:20 +00001501 }
mpagenko38662d02021-08-11 09:45:19 +00001502 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1503 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1504 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
mpagenkoaa3afe92021-05-21 16:20:58 +00001505 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001506 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1507 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1508 // TODO!!!: error treatment?
1509 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1510 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1511 return
1512 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001513 default:
1514 {
1515 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1516 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1517 return
1518 }
1519 }
1520}
1521
mpagenko38662d02021-08-11 09:45:19 +00001522//abortOnOmciError aborts the upgrade processing with OMCI_TRANSFER_ERROR indication
1523func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool,
1524 aImageState voltha.ImageState_ImageActivationState) {
1525 oFsm.mutexUpgradeParams.Lock()
1526 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1527 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1528 oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
1529 if aImageState != voltha.ImageState_IMAGE_UNKNOWN {
1530 // update image state only in case some explicite state is given (otherwise the existing state is used)
1531 oFsm.volthaImageState = aImageState
1532 }
1533 oFsm.mutexUpgradeParams.Unlock()
1534 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1535 if oFsm.pAdaptFsm != nil {
1536 var err error
1537 if aAsync { //asynchronous call requested to ensure state transition
1538 go func(a_pAFsm *AdapterFsm) {
1539 if a_pAFsm.pFsm != nil {
1540 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1541 }
1542 }(oFsm.pAdaptFsm)
1543 } else {
1544 if oFsm.pAdaptFsm.pFsm != nil {
1545 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1546 }
1547 }
1548 if err != nil {
1549 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1550 "device-id": oFsm.deviceID, "error": err})
1551 }
1552 }
1553}
1554
mpagenkoc26d4c02021-05-06 14:27:57 +00001555//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
mpagenko38662d02021-08-11 09:45:19 +00001556// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
1557func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
1558 aWaitChannel chan bool) {
mpagenkoc26d4c02021-05-06 14:27:57 +00001559 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
mpagenko38662d02021-08-11 09:45:19 +00001560 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
mpagenkoc26d4c02021-05-06 14:27:57 +00001561 oFsm.isWaitingForAdapterDlResponse = true
1562 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001563 aSyncChannel <- struct{}{}
mpagenko80622a52021-02-09 16:53:23 +00001564 select {
1565 // maybe be also some outside cancel (but no context modeled for the moment ...)
1566 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001567 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1568 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1569 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1570 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1571 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1572 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1573 oFsm.isWaitingForAdapterDlResponse = false
1574 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001575 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenkoc26d4c02021-05-06 14:27:57 +00001576 return
1577
1578 case success := <-aWaitChannel:
1579 if success {
1580 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1581 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1582 oFsm.isWaitingForAdapterDlResponse = false
1583 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1584 //let the upgrade process proceed
1585 pUpgradeFsm := oFsm.pAdaptFsm
1586 if pUpgradeFsm != nil {
1587 _ = pUpgradeFsm.pFsm.Event(upgradeEvPrepareSwDownload)
1588 } else {
1589 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1590 }
1591 return
1592 }
1593 // waiting was aborted (probably on external request)
1594 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1595 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1596 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1597 oFsm.isWaitingForAdapterDlResponse = false
1598 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1599 //the upgrade process has to be aborted
mpagenko38662d02021-08-11 09:45:19 +00001600 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenkoc26d4c02021-05-06 14:27:57 +00001601 return
mpagenko80622a52021-02-09 16:53:23 +00001602 }
1603}
mpagenkoc26d4c02021-05-06 14:27:57 +00001604
1605//waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1606func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1607 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1608 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1609 "duration": downloadToOnuTimeout})
1610 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1611 oFsm.isWaitingForOnuDlResponse = true
1612 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1613 select {
1614 // maybe be also some outside cancel (but no context modeled for the moment ...)
1615 // case <-ctx.Done():
1616 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1617 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1618 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1619 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
1620 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1621 oFsm.isWaitingForOnuDlResponse = false
1622 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1623 //the upgrade process has to be aborted
mpagenko38662d02021-08-11 09:45:19 +00001624 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenkoc26d4c02021-05-06 14:27:57 +00001625 return
1626
1627 case success := <-aWaitChannel:
1628 if success {
1629 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
1630 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1631 oFsm.isWaitingForOnuDlResponse = false
1632 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1633 //all fine, let the FSM proceed like defined from the sender of this event
1634 return
1635 }
1636 // waiting was aborted (assumed here to be caused by
1637 // error detection or cancel at download after upgrade FSM reset/abort)
1638 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
1639 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1640 oFsm.isWaitingForOnuDlResponse = false
1641 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1642 return
1643 }
1644}