blob: 49b320d0e76af23a3c53d054b744f910a4b53e54 [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
mpagenko9c225032021-10-15 14:26:49 +000050// tEndSwDlResponseResult - Response result from EndSwDownload as used in channel indication
51type tUpgradePhase uint8
52
mpagenko80622a52021-02-09 16:53:23 +000053const (
mpagenko9c225032021-10-15 14:26:49 +000054 // undefined phase
55 cUpgradeUndefined tUpgradePhase = iota
56 // downloading image
57 cUpgradeDownloading
58 // image downloaded
59 cUpgradeDownloaded
60 // activating image
61 cUpgradeActivating
62 // image activated
63 cUpgradeActivated
64 // committing image
65 cUpgradeCommitting
66 // image committed
67 cUpgradeCommitted
68)
69
70// tEndSwDlResponseResult - Response result from EndSwDownload as used in channel indication
71type tEndSwDlResponseResult uint8
72
73const (
74 // response success
75 cEndSwDlResponseSuccess tEndSwDlResponseResult = iota
76 // response busy (repeat)
77 cEndSwDlResponseBusy
78 // response error or abort waiting for response
79 cEndSwDlResponseAbort
80)
81
82// upgrade FSM related events
83const (
mpagenko80622a52021-02-09 16:53:23 +000084 upgradeEvStart = "upgradeEvStart"
mpagenko9c225032021-10-15 14:26:49 +000085 upgradeEvDisable = "upgradeEvDisable"
mpagenkoc26d4c02021-05-06 14:27:57 +000086 upgradeEvAdapterDownload = "upgradeEvAdapterDownload"
mpagenko80622a52021-02-09 16:53:23 +000087 upgradeEvPrepareSwDownload = "upgradeEvPrepareSwDownload"
88 upgradeEvRxStartSwDownload = "upgradeEvRxStartSwDownload"
89 upgradeEvWaitWindowAck = "upgradeEvWaitWindowAck"
90 upgradeEvContinueNextWindow = "upgradeEvContinueNextWindow"
91 upgradeEvEndSwDownload = "upgradeEvEndSwDownload"
mpagenko59498c12021-03-18 14:15:15 +000092 upgradeEvWaitEndDownload = "upgradeEvWaitEndDownload"
93 upgradeEvContinueFinalize = "upgradeEvContinueFinalize"
mpagenko9c225032021-10-15 14:26:49 +000094 upgradeEvCheckImageName = "upgradeEvCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +000095 upgradeEvWaitForActivate = "upgradeEvWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000096 upgradeEvRequestActivate = "upgradeEvRequestActivate"
mpagenko183647c2021-06-08 15:25:04 +000097 upgradeEvActivationDone = "upgradeEvActivationDone"
mpagenko80622a52021-02-09 16:53:23 +000098 upgradeEvWaitForCommit = "upgradeEvWaitForCommit"
99 upgradeEvCommitSw = "upgradeEvCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +0000100 upgradeEvCheckCommitted = "upgradeEvCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +0000101
102 //upgradeEvTimeoutSimple = "upgradeEvTimeoutSimple"
103 //upgradeEvTimeoutMids = "upgradeEvTimeoutMids"
mpagenko9c225032021-10-15 14:26:49 +0000104 upgradeEvReset = "upgradeEvReset"
105 upgradeEvAbort = "upgradeEvAbort"
106 upgradeEvRestart = "upgradeEvRestart"
107 upgradeEvAbortSwDownload = "upgradeEvAbortSwDownload"
mpagenko80622a52021-02-09 16:53:23 +0000108)
109
mpagenko9c225032021-10-15 14:26:49 +0000110// upgrade FSM related states
mpagenko80622a52021-02-09 16:53:23 +0000111const (
mpagenko80622a52021-02-09 16:53:23 +0000112 upgradeStDisabled = "upgradeStDisabled"
113 upgradeStStarting = "upgradeStStarting"
mpagenkoc26d4c02021-05-06 14:27:57 +0000114 upgradeStWaitingAdapterDL = "upgradeStWaitingAdapterDL"
mpagenko80622a52021-02-09 16:53:23 +0000115 upgradeStPreparingDL = "upgradeStPreparingDL"
116 upgradeStDLSection = "upgradeStDLSection"
117 upgradeStVerifyWindow = "upgradeStVerifyWindow"
118 upgradeStFinalizeDL = "upgradeStFinalizeDL"
mpagenko59498c12021-03-18 14:15:15 +0000119 upgradeStWaitEndDL = "upgradeStWaitEndDL"
mpagenko9c225032021-10-15 14:26:49 +0000120 upgradeStCheckImageName = "upgradeStCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +0000121 upgradeStWaitForActivate = "upgradeStWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +0000122 upgradeStRequestingActivate = "upgradeStRequestingActivate"
mpagenko183647c2021-06-08 15:25:04 +0000123 upgradeStActivated = "upgradeStActivated"
mpagenko80622a52021-02-09 16:53:23 +0000124 upgradeStWaitForCommit = "upgradeStWaitForCommit"
125 upgradeStCommitSw = "upgradeStCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +0000126 upgradeStCheckCommitted = "upgradeStCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +0000127 upgradeStResetting = "upgradeStResetting"
mpagenko9c225032021-10-15 14:26:49 +0000128 upgradeStRestarting = "upgradeStRestarting"
129 upgradeStAbortingDL = "upgradeStAbortingDL"
mpagenko80622a52021-02-09 16:53:23 +0000130)
131
132//required definition for IdleState detection for activities on OMCI
133const cOnuUpgradeFsmIdleState = upgradeStWaitForCommit
134
135//OnuUpgradeFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
136type OnuUpgradeFsm struct {
137 pDeviceHandler *deviceHandler
138 pDownloadManager *adapterDownloadManager
mpagenkoc26d4c02021-05-06 14:27:57 +0000139 pFileManager *fileDownloadManager //used from R2.8 with new API version
mpagenko80622a52021-02-09 16:53:23 +0000140 deviceID string
mpagenko9c225032021-10-15 14:26:49 +0000141 pDevEntry *OnuDeviceEntry
mpagenko80622a52021-02-09 16:53:23 +0000142 pOmciCC *omciCC
143 pOnuDB *onuDeviceDB
144 requestEvent OnuDeviceEvent
145 //omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
mpagenkoc26d4c02021-05-06 14:27:57 +0000146 pAdaptFsm *AdapterFsm
147 pImageDsc *voltha.ImageDownload
148 imageBuffer []byte
149 origImageLength uint32 //as also limited by OMCI
150 imageCRC uint32 //as per OMCI - ITU I.363.5 crc
151 imageLength uint32 //including last bytes padding
152 omciDownloadWindowSizeLimit uint8 //windowSize-1 in sections
153 omciDownloadWindowSizeLast uint8 //number of sections in last window
154 noOfSections uint32 //uint32 range for sections should be sufficient for very long images
155 nextDownloadSectionsAbsolute uint32 //number of next section to download in overall image
156 nextDownloadSectionsWindow uint8 //number of next section to download within current window
157 noOfWindows uint32 //uint32 range for windows should be sufficient for very long images
158 nextDownloadWindow uint32 //number of next window to download
159 inactiveImageMeID uint16 //ME-ID of the inactive image
160 downloadToOnuTimeout4MB time.Duration //timeout for downloading the image to the ONU for a 4MB image slice
161 omciSectionInterleaveDelay time.Duration //DownloadSectionInterleave delay in milliseconds
162 delayEndSwDl bool //flag to provide a delay between last section and EndSwDl
mpagenko9c225032021-10-15 14:26:49 +0000163 repeatAbort bool //flag to indicate if OMCI EndSwDownload (abort) is to be repeated
mpagenkoc26d4c02021-05-06 14:27:57 +0000164 pLastTxMeInstance *me.ManagedEntity
165 waitCountEndSwDl uint8 //number, how often is waited for EndSwDl at maximum
166 waitDelayEndSwDl time.Duration //duration, how long is waited before next request on EndSwDl
167 chReceiveExpectedResponse chan bool
mpagenkoaa3afe92021-05-21 16:20:58 +0000168 useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
169 mutexUpgradeParams sync.RWMutex //mutex to protect members for parallel function requests and omci response processing
170 imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
171 imageIdentifier string //name of the image as used in the adapter
mpagenkoc26d4c02021-05-06 14:27:57 +0000172 mutexIsAwaitingAdapterDlResponse sync.RWMutex
173 chAdapterDlReady chan bool
174 isWaitingForAdapterDlResponse bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000175 chOnuDlReady chan bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000176 activateImage bool
177 commitImage bool
mpagenko9c225032021-10-15 14:26:49 +0000178 mutexAbortRequest sync.RWMutex
179 abortRequested voltha.ImageState_ImageFailureReason
180 conditionalCancelRequested bool
181 upgradePhase tUpgradePhase
mpagenkoaa3afe92021-05-21 16:20:58 +0000182 volthaDownloadState voltha.ImageState_ImageDownloadState
183 volthaDownloadReason voltha.ImageState_ImageFailureReason
184 volthaImageState voltha.ImageState_ImageActivationState
mpagenko9c225032021-10-15 14:26:49 +0000185 downloadReasonCached voltha.ImageState_ImageFailureReason
186 isEndSwDlOpen bool
187 chReceiveAbortEndSwDlResponse chan tEndSwDlResponseResult
mpagenko80622a52021-02-09 16:53:23 +0000188}
189
190//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
191// of ONU UNI ports via OMCI
192func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler *deviceHandler,
mpagenko15ff4a52021-03-02 10:09:20 +0000193 apDevEntry *OnuDeviceEntry, apOnuDB *onuDeviceDB,
mpagenko80622a52021-02-09 16:53:23 +0000194 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message) *OnuUpgradeFsm {
195 instFsm := &OnuUpgradeFsm{
mpagenko59498c12021-03-18 14:15:15 +0000196 pDeviceHandler: apDeviceHandler,
197 deviceID: apDeviceHandler.deviceID,
mpagenko9c225032021-10-15 14:26:49 +0000198 pDevEntry: apDevEntry,
mpagenko59498c12021-03-18 14:15:15 +0000199 pOmciCC: apDevEntry.PDevOmciCC,
200 pOnuDB: apOnuDB,
201 requestEvent: aRequestEvent,
202 omciDownloadWindowSizeLimit: cOmciDownloadWindowSizeLimit,
203 omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000204 downloadToOnuTimeout4MB: apDeviceHandler.pOpenOnuAc.dlToOnuTimeout4M,
mpagenko59498c12021-03-18 14:15:15 +0000205 waitCountEndSwDl: cWaitCountEndSwDl,
206 waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
mpagenko9c225032021-10-15 14:26:49 +0000207 upgradePhase: cUpgradeUndefined,
208 volthaDownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
mpagenkoaa3afe92021-05-21 16:20:58 +0000209 volthaDownloadReason: voltha.ImageState_NO_ERROR,
210 volthaImageState: voltha.ImageState_IMAGE_UNKNOWN,
mpagenko9c225032021-10-15 14:26:49 +0000211 abortRequested: voltha.ImageState_NO_ERROR,
mpagenko80622a52021-02-09 16:53:23 +0000212 }
mpagenko59498c12021-03-18 14:15:15 +0000213 instFsm.chReceiveExpectedResponse = make(chan bool)
mpagenkoc26d4c02021-05-06 14:27:57 +0000214 instFsm.chAdapterDlReady = make(chan bool)
215 instFsm.chOnuDlReady = make(chan bool)
mpagenko9c225032021-10-15 14:26:49 +0000216 instFsm.chReceiveAbortEndSwDlResponse = make(chan tEndSwDlResponseResult)
mpagenko80622a52021-02-09 16:53:23 +0000217
218 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
219 if instFsm.pAdaptFsm == nil {
220 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
221 "device-id": instFsm.deviceID})
222 return nil
223 }
224 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
225 upgradeStDisabled,
226 fsm.Events{
227 {Name: upgradeEvStart, Src: []string{upgradeStDisabled}, Dst: upgradeStStarting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000228 {Name: upgradeEvAdapterDownload, Src: []string{upgradeStStarting}, Dst: upgradeStWaitingAdapterDL},
229 {Name: upgradeEvPrepareSwDownload, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL}, Dst: upgradeStPreparingDL},
mpagenko80622a52021-02-09 16:53:23 +0000230 {Name: upgradeEvRxStartSwDownload, Src: []string{upgradeStPreparingDL}, Dst: upgradeStDLSection},
231 {Name: upgradeEvWaitWindowAck, Src: []string{upgradeStDLSection}, Dst: upgradeStVerifyWindow},
232 {Name: upgradeEvContinueNextWindow, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStDLSection},
233 {Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
mpagenko59498c12021-03-18 14:15:15 +0000234 {Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
235 {Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
mpagenko9c225032021-10-15 14:26:49 +0000236 //UpgradeStCheckImageName only used with useAPIVersion43
237 {Name: upgradeEvCheckImageName, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStCheckImageName},
238 //UpgradeEvWaitForActivate state transitions depend on useAPIVersion43
239 {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL, upgradeStCheckImageName}, Dst: upgradeStWaitForActivate},
240 //UpgradeEvRequestActivate state transitions depend on useAPIVersion43
241 {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStCheckImageName,
242 upgradeStWaitForActivate}, Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
mpagenko183647c2021-06-08 15:25:04 +0000243 {Name: upgradeEvActivationDone, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStActivated},
mpagenko80622a52021-02-09 16:53:23 +0000244 {Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
mpagenko1f8e8822021-06-25 14:10:21 +0000245 {Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
246 upgradeStActivated}, Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
mpagenko15ff4a52021-03-02 10:09:20 +0000247 {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000248
249 /*
250 {Name: upgradeEvTimeoutSimple, Src: []string{
251 upgradeStCreatingDot1PMapper, upgradeStCreatingMBPCD, upgradeStSettingTconts, upgradeStSettingDot1PMapper}, Dst: upgradeStStarting},
252 {Name: upgradeEvTimeoutMids, Src: []string{
253 upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
254 */
255 // exceptional treatments
mpagenko1f8e8822021-06-25 14:10:21 +0000256 //on upgradeEvReset: upgradeStRequestingActivate, upgradeStWaitForCommit and upgradeStActivated are not reset
257 // (to let the FSM survive the expected OnuDown indication)
mpagenkoc26d4c02021-05-06 14:27:57 +0000258 {Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko9c225032021-10-15 14:26:49 +0000259 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
260 upgradeStWaitForActivate,
261 upgradeStCommitSw, upgradeStCheckCommitted, upgradeStAbortingDL},
mpagenko80622a52021-02-09 16:53:23 +0000262 Dst: upgradeStResetting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000263 {Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko9c225032021-10-15 14:26:49 +0000264 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
265 upgradeStWaitForActivate,
266 upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit,
267 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000268 Dst: upgradeStResetting},
mpagenko9c225032021-10-15 14:26:49 +0000269 {Name: upgradeEvAbortSwDownload, Src: []string{upgradeStResetting}, Dst: upgradeStAbortingDL},
270 {Name: upgradeEvRestart, Src: []string{upgradeStResetting, upgradeStAbortingDL}, Dst: upgradeStRestarting},
271 {Name: upgradeEvDisable, Src: []string{upgradeStRestarting}, Dst: upgradeStDisabled},
mpagenko80622a52021-02-09 16:53:23 +0000272 },
273 fsm.Callbacks{
274 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
275 "enter_" + upgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
mpagenkoc26d4c02021-05-06 14:27:57 +0000276 "enter_" + upgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000277 "enter_" + upgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
278 "enter_" + upgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
279 "enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
280 "enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
mpagenko59498c12021-03-18 14:15:15 +0000281 "enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
mpagenko9c225032021-10-15 14:26:49 +0000282 "enter_" + upgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000283 "enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
284 "enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
mpagenko15ff4a52021-03-02 10:09:20 +0000285 "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000286 "enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
mpagenko9c225032021-10-15 14:26:49 +0000287 "enter_" + upgradeStAbortingDL: func(e *fsm.Event) { instFsm.enterAbortingDL(ctx, e) },
288 "enter_" + upgradeStRestarting: func(e *fsm.Event) { instFsm.enterRestarting(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000289 "enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
290 },
291 )
292 if instFsm.pAdaptFsm.pFsm == nil {
293 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
294 "device-id": instFsm.deviceID})
295 return nil
296 }
297
298 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
299 return instFsm
300}
301
302//SetDownloadParams configures the needed parameters for a specific download to the ONU
mpagenkoc26d4c02021-05-06 14:27:57 +0000303// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000304func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
305 apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
mpagenko80622a52021-02-09 16:53:23 +0000306 pBaseFsm := oFsm.pAdaptFsm.pFsm
307 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000308 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000309 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
310 "device-id": oFsm.deviceID, "image-description": apImageDsc})
mpagenko15ff4a52021-03-02 10:09:20 +0000311 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000312 oFsm.pImageDsc = apImageDsc
313 oFsm.pDownloadManager = apDownloadManager
Holger Hildebrandtac1e0592021-06-03 15:16:49 +0000314 oFsm.activateImage = true
315 oFsm.commitImage = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000316 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000317
318 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000319 // let the upgrade FSM proceed to PreparingDL
mpagenko80622a52021-02-09 16:53:23 +0000320 _ = aPBaseFsm.Event(upgradeEvPrepareSwDownload)
321 }(pBaseFsm)
322 return nil
323 }
324 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
325 "device-id": oFsm.deviceID})
326 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
327}
328
mpagenkoc26d4c02021-05-06 14:27:57 +0000329//SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
330// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
331// called from 'new' API Download_onu_image
332func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
333 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *fileDownloadManager,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000334 aImageIdentifier string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000335 oFsm.mutexUpgradeParams.Lock()
336 var pBaseFsm *fsm.FSM = nil
337 if oFsm.pAdaptFsm != nil {
338 pBaseFsm = oFsm.pAdaptFsm.pFsm
339 }
340 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
341 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
342 "device-id": oFsm.deviceID, "image-description": apImageRequest})
343 oFsm.useAPIVersion43 = true
344 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
345 oFsm.pFileManager = apDownloadManager
346 oFsm.imageIdentifier = aImageIdentifier
347 oFsm.imageVersion = apImageRequest.Image.Version
348 oFsm.activateImage = apImageRequest.ActivateOnSuccess
349 oFsm.commitImage = apImageRequest.CommitOnSuccess
mpagenko9c225032021-10-15 14:26:49 +0000350 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //state change indication for download request
mpagenkoc26d4c02021-05-06 14:27:57 +0000351 oFsm.mutexUpgradeParams.Unlock()
352 _ = pBaseFsm.Event(upgradeEvAdapterDownload) //no need to call the FSM event in background here
353 return nil
354 }
355 oFsm.mutexUpgradeParams.Unlock()
356 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
357 "device-id": oFsm.deviceID})
358 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
359}
360
361//SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
362// called from 'new' API Activate_onu_image
363func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
364 aImageIdentifier string, aCommit bool) error {
mpagenko9c225032021-10-15 14:26:49 +0000365 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
366 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
mpagenkoc26d4c02021-05-06 14:27:57 +0000367 oFsm.mutexUpgradeParams.Lock()
368 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
369 // (as long as the Imageidentifier is correct)
mpagenkoc26d4c02021-05-06 14:27:57 +0000370 if aImageIdentifier != oFsm.imageIdentifier {
371 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
372 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
373 oFsm.mutexUpgradeParams.Unlock()
374 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
375 oFsm.deviceID))
376 }
377 oFsm.activateImage = true
378 oFsm.commitImage = aCommit
379 oFsm.mutexUpgradeParams.Unlock()
380 var pBaseFsm *fsm.FSM = nil
381 if oFsm.pAdaptFsm != nil {
382 pBaseFsm = oFsm.pAdaptFsm.pFsm
383 }
384 if pBaseFsm != nil {
385 if pBaseFsm.Is(upgradeStWaitForActivate) {
386 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
387 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenko9c225032021-10-15 14:26:49 +0000388 } else {
389 logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
390 "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000391 }
392 return nil
393 }
394 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
395 "device-id": oFsm.deviceID})
396 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
397}
398
399//SetActivationParamsStart starts upgrade processing with immediate activation
400// called from 'new' API Activate_onu_image
401func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
402 oFsm.mutexUpgradeParams.Lock()
403 var pBaseFsm *fsm.FSM = nil
404 if oFsm.pAdaptFsm != nil {
405 pBaseFsm = oFsm.pAdaptFsm.pFsm
406 }
407 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
408 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
409 "device-id": oFsm.deviceID, "image-version": aImageVersion})
410 oFsm.useAPIVersion43 = true
411 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
412 oFsm.imageVersion = aImageVersion
413 oFsm.activateImage = true
414 oFsm.commitImage = aCommit
mpagenko9c225032021-10-15 14:26:49 +0000415 // indicate start of the upgrade activity
416 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000417 oFsm.mutexUpgradeParams.Unlock()
418 //directly request the FSM to activate the image
419 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
420 return nil
421 }
422 oFsm.mutexUpgradeParams.Unlock()
423 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
424 "device-id": oFsm.deviceID})
425 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
426}
427
428//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
429// called from 'new' API Commit_onu_image
mpagenko9c225032021-10-15 14:26:49 +0000430func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
431 aImageIdentifier string, aImageVersion string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000432 oFsm.mutexUpgradeParams.Lock()
433 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
434 // (as long as the Imageidentifier is correct)
435 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
mpagenko9c225032021-10-15 14:26:49 +0000436 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "image-version": aImageVersion})
437 if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000438 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
mpagenko9c225032021-10-15 14:26:49 +0000439 "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
440 "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
mpagenkoc26d4c02021-05-06 14:27:57 +0000441 oFsm.mutexUpgradeParams.Unlock()
442 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
443 oFsm.deviceID))
444 }
445 oFsm.commitImage = true
446 oFsm.mutexUpgradeParams.Unlock()
447 var pBaseFsm *fsm.FSM = nil
448 if oFsm.pAdaptFsm != nil {
449 pBaseFsm = oFsm.pAdaptFsm.pFsm
450 }
451 if pBaseFsm != nil {
mpagenko183647c2021-06-08 15:25:04 +0000452 //let the FSM decide if it is ready to process the event
453 logger.Debugw(ctx, "OnuUpgradeFsm requesting commit",
454 log.Fields{"device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
455 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000456 return nil
457 }
mpagenko9c225032021-10-15 14:26:49 +0000458 //should never occur
mpagenkoc26d4c02021-05-06 14:27:57 +0000459 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
460 "device-id": oFsm.deviceID})
461 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
462}
463
464//SetCommitmentParamsStart starts upgrade processing with immediate commitment
465// called from 'new' API Commit_onu_image
466func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
467 oFsm.mutexUpgradeParams.Lock()
468 var pBaseFsm *fsm.FSM = nil
469 if oFsm.pAdaptFsm != nil {
470 pBaseFsm = oFsm.pAdaptFsm.pFsm
471 }
472 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
473 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
474 "device-id": oFsm.deviceID, "image-version": aImageVersion})
475 oFsm.useAPIVersion43 = true
476 oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
477 oFsm.imageVersion = aImageVersion
478 oFsm.commitImage = true
mpagenko9c225032021-10-15 14:26:49 +0000479 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000480 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000481 //directly request the FSM to commit the image
mpagenkoc26d4c02021-05-06 14:27:57 +0000482 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
483 return nil
484 }
485 oFsm.mutexUpgradeParams.Unlock()
486 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
487 "device-id": oFsm.deviceID})
488 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
489}
490
mpagenko1f8e8822021-06-25 14:10:21 +0000491//GetCommitFlag delivers the commit flag that was configured here
492func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
493 oFsm.mutexUpgradeParams.RLock()
494 defer oFsm.mutexUpgradeParams.RUnlock()
495 return oFsm.commitImage
496}
497
mpagenko9c225032021-10-15 14:26:49 +0000498//GetImageStates delivers the download/image states as per device protobuf or error indication
mpagenkoaa3afe92021-05-21 16:20:58 +0000499func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
mpagenko9c225032021-10-15 14:26:49 +0000500 aImageIdentifier string, aVersion string) *voltha.ImageState {
mpagenkoaa3afe92021-05-21 16:20:58 +0000501 pImageState := &voltha.ImageState{}
mpagenko9c225032021-10-15 14:26:49 +0000502 pImageState.Version = aVersion //version as requested
mpagenkoaa3afe92021-05-21 16:20:58 +0000503 // check if the request refers to some active image/version of the processing
504 oFsm.mutexUpgradeParams.RLock()
505 if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
506 pImageState.DownloadState = oFsm.volthaDownloadState
507 pImageState.Reason = oFsm.volthaDownloadReason
508 pImageState.ImageState = oFsm.volthaImageState
509 } else {
510 pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
511 pImageState.Reason = voltha.ImageState_NO_ERROR
512 pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
513 }
514 oFsm.mutexUpgradeParams.RUnlock()
mpagenko9c225032021-10-15 14:26:49 +0000515 return pImageState
mpagenkoaa3afe92021-05-21 16:20:58 +0000516}
517
mpagenko9c225032021-10-15 14:26:49 +0000518//SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
519func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
mpagenko183647c2021-06-08 15:25:04 +0000520 oFsm.mutexUpgradeParams.Lock()
521 defer oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000522 oFsm.upgradePhase = cUpgradeActivated
523 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
mpagenko183647c2021-06-08 15:25:04 +0000524}
525
mpagenkoc26d4c02021-05-06 14:27:57 +0000526//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko9c225032021-10-15 14:26:49 +0000527func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
528 aReason voltha.ImageState_ImageFailureReason) {
529 pAdaptFsm := oFsm.pAdaptFsm
530 if pAdaptFsm == nil || pAdaptFsm.pFsm == nil {
531 logger.Warnw(ctx, "OnuUpgradeFsm cancel, but FSM invalid", log.Fields{
532 "device-id": oFsm.deviceID})
533 return
534 }
535 logger.Debugw(ctx, "OnuUpgradeFsm start canceling", log.Fields{
536 "device-id": oFsm.deviceID, "in fsm-state": pAdaptFsm.pFsm.Current()})
537 oFsm.mutexAbortRequest.Lock()
538 oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
539 oFsm.mutexAbortRequest.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000540 //mutex protection is required for possible concurrent access to FSM members
541 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
542 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
543 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
544 if oFsm.isWaitingForAdapterDlResponse {
545 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
546 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
547 oFsm.chAdapterDlReady <- false
548 } else {
549 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
550 }
551 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
552
553 // 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 +0000554 // specific here: See definition of state changes: some states are excluded from reset for possible later commit
mpagenko9c225032021-10-15 14:26:49 +0000555 pAdaptFsm = oFsm.pAdaptFsm
556 if pAdaptFsm != nil && pAdaptFsm.pFsm != nil {
mpagenkoc26d4c02021-05-06 14:27:57 +0000557 // calling FSM events in background to avoid blocking of the caller
mpagenko9c225032021-10-15 14:26:49 +0000558 go func(apFsm *fsm.FSM) {
559 if apFsm.Is(upgradeStWaitEndDL) {
560 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
561 } else if apFsm.Is(upgradeStAbortingDL) {
562 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //abort waiting on EndDownloadResponse
563 }
564
565 var err error
566 if abCompleteAbort {
567 // in case of unconditional abort request the ImageState is set immediately
568 oFsm.mutexUpgradeParams.Lock()
569 //any previous lingering conditional cancelRequest is superseded by this abortion
570 oFsm.conditionalCancelRequested = false
571 oFsm.volthaDownloadReason = aReason
572 oFsm.mutexUpgradeParams.Unlock()
573 err = apFsm.Event(upgradeEvAbort) //as unconditional default FSM cancellation
574 } else {
575 //at conditional abort request the image states are set when reaching the reset state
576 oFsm.mutexUpgradeParams.Lock()
577 oFsm.conditionalCancelRequested = true
578 oFsm.mutexUpgradeParams.Unlock()
579 err = apFsm.Event(upgradeEvReset) //as state-conditional default FSM cleanup
580 }
581 if err != nil {
582 //error return is expected in case of conditional request and no state transition
583 logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
584 "device-id": oFsm.deviceID, "error": err})
585 }
586 logger.Debugw(ctx, "OnuUpgradeFsm canceling done", log.Fields{
587 "device-id": oFsm.deviceID})
588 }(pAdaptFsm.pFsm)
589 } else { //the FSM seems already to be in some released state
590 logger.Warnw(ctx, "OnuUpgradeFsm canceling without FSM event", log.Fields{
591 "device-id": oFsm.deviceID, "in fsm-state": pAdaptFsm.pFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000592 }
593}
594
mpagenko80622a52021-02-09 16:53:23 +0000595func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
596 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
597 "device-id": oFsm.deviceID})
598
599 // start go routine for processing of LockState messages
600 go oFsm.processOmciUpgradeMessages(ctx)
601}
602
mpagenkoc26d4c02021-05-06 14:27:57 +0000603//enterWaitingAdapterDL state can only be reached with useAPIVersion43
604func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
605 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
606 "device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +0000607 syncChannel := make(chan struct{})
608 go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
609 //block until the wait routine is really blocked on chAdapterDlReady
610 <-syncChannel
mpagenkoc26d4c02021-05-06 14:27:57 +0000611 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
612}
613
mpagenko80622a52021-02-09 16:53:23 +0000614func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
615 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
616 "device-id": oFsm.deviceID})
617
mpagenkoc26d4c02021-05-06 14:27:57 +0000618 var fileLen int64
619 var err error
mpagenkoaa3afe92021-05-21 16:20:58 +0000620 oFsm.mutexUpgradeParams.Lock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000621 if oFsm.useAPIVersion43 {
622 //with the new API structure download to adapter is implicit and we have to wait until the image is available
623 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
624 } else {
625 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
626 }
mpagenko80622a52021-02-09 16:53:23 +0000627 if err != nil || fileLen > int64(cMaxUint32) {
mpagenko9c225032021-10-15 14:26:49 +0000628 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000629 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000630 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
631 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
632 pBaseFsm := oFsm.pAdaptFsm
633 // Can't call FSM Event directly, decoupling it
634 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000635 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000636 }(pBaseFsm)
637 return
638 }
639
mpagenkoc26d4c02021-05-06 14:27:57 +0000640 //copy file content to buffer
mpagenko80622a52021-02-09 16:53:23 +0000641 oFsm.imageBuffer = make([]byte, fileLen)
mpagenkoc26d4c02021-05-06 14:27:57 +0000642 if oFsm.useAPIVersion43 {
643 oFsm.imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
644 } else {
645 oFsm.imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
646 }
mpagenko80622a52021-02-09 16:53:23 +0000647 if err != nil {
mpagenko9c225032021-10-15 14:26:49 +0000648 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000649 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000650 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
651 "device-id": oFsm.deviceID, "error": err})
652 pBaseFsm := oFsm.pAdaptFsm
653 // Can't call FSM Event directly, decoupling it
654 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000655 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000656 }(pBaseFsm)
657 return
658 }
659
660 oFsm.noOfSections = uint32(fileLen / cOmciDownloadSectionSize)
661 if fileLen%cOmciDownloadSectionSize > 0 {
mpagenkoc26d4c02021-05-06 14:27:57 +0000662 bufferPadding := make([]byte, cOmciDownloadSectionSize-uint32((fileLen)%cOmciDownloadSectionSize))
mpagenko80622a52021-02-09 16:53:23 +0000663 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
mpagenkoc26d4c02021-05-06 14:27:57 +0000664 oFsm.imageBuffer = append(oFsm.imageBuffer[:(fileLen)], bufferPadding...)
mpagenko80622a52021-02-09 16:53:23 +0000665 oFsm.noOfSections++
666 }
667 oFsm.origImageLength = uint32(fileLen)
668 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000669 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
670 "MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
671 "ImageSize": oFsm.imageLength, "original file size": fileLen})
672 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
mpagenkoaa3afe92021-05-21 16:20:58 +0000673
674 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000675
676 // flush commMetricsChan
677 select {
678 case <-oFsm.chOnuDlReady:
679 logger.Debug(ctx, "flushed OnuDlReady channel")
680 default:
681 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000682 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
683
mpagenko9c225032021-10-15 14:26:49 +0000684 err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000685 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
686 if err != nil {
687 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
688 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000689 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000690 return
691 }
mpagenko9c225032021-10-15 14:26:49 +0000692 oFsm.isEndSwDlOpen = true
mpagenko80622a52021-02-09 16:53:23 +0000693}
694
695func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
696 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
697 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
mpagenko9c225032021-10-15 14:26:49 +0000698 //use a background routine to send the multiple download sections frames in a loop
699 // in order to avoid blocking on synchrounous event calls for the entire (long) processing time
700 go oFsm.runSwDlSectionWindow(ctx)
701}
mpagenko80622a52021-02-09 16:53:23 +0000702
mpagenko9c225032021-10-15 14:26:49 +0000703//runSwDlSectionWindow runs a loop to send all DlSection frames of one window in background
704// may be aborted by parallel change of abortRequested
705func (oFsm *OnuUpgradeFsm) runSwDlSectionWindow(ctx context.Context) {
mpagenko80622a52021-02-09 16:53:23 +0000706 var windowAckRequest uint8 = 0
707 var bufferStartOffset uint32
708 var bufferEndOffset uint32
709 var downloadSection []byte
710 framePrint := false //default no printing of downloadSection frames
mpagenkoaa3afe92021-05-21 16:20:58 +0000711 oFsm.mutexUpgradeParams.Lock()
mpagenko9c225032021-10-15 14:26:49 +0000712 oFsm.upgradePhase = cUpgradeDownloading //start of downloading image to ONU
mpagenko80622a52021-02-09 16:53:23 +0000713 if oFsm.nextDownloadSectionsAbsolute == 0 {
714 //debug print of first section frame
715 framePrint = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000716 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
mpagenko80622a52021-02-09 16:53:23 +0000717 }
mpagenko80622a52021-02-09 16:53:23 +0000718 for {
mpagenko9c225032021-10-15 14:26:49 +0000719 oFsm.mutexAbortRequest.RLock()
720 // this way out of the section download loop on abort request
721 if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
722 //states are updated when entering the reset state ...
723 oFsm.volthaDownloadReason = oFsm.abortRequested
724 oFsm.mutexAbortRequest.RUnlock()
725 oFsm.mutexUpgradeParams.Unlock()
726 pUpgradeFsm := oFsm.pAdaptFsm
727 if pUpgradeFsm != nil {
728 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
729 logger.Debugw(ctx, "aborting runSwDlSectionWindow", log.Fields{
730 "device-id": oFsm.deviceID, "reason": oFsm.volthaDownloadReason})
731 return
732 }
733 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
734 return
735 }
736 oFsm.mutexAbortRequest.RUnlock()
737
mpagenko80622a52021-02-09 16:53:23 +0000738 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
739 bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
740 logger.Debugw(ctx, "DlSection values are", log.Fields{
741 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
742 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
743 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
744 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
745 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
746 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
747 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
mpagenko9c225032021-10-15 14:26:49 +0000748 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000749 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000750 //logical error -- reset the FSM
mpagenko9c225032021-10-15 14:26:49 +0000751 pUpgradeFsm := oFsm.pAdaptFsm
752 if pUpgradeFsm != nil {
753 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
754 return
755 }
756 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000757 return
758 }
759 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
760 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
761 windowAckRequest = 1
762 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
763 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
764 }
765 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
766 windowAckRequest = 1
767 framePrint = true //debug print of last frame
mpagenko15ff4a52021-03-02 10:09:20 +0000768 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
769 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000770 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
771 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000772 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko9c225032021-10-15 14:26:49 +0000773 err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000774 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
775 if err != nil {
776 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000777 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000778 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +0000779 return
780 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000781 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000782 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
783 if windowAckRequest == 1 {
mpagenkoaa3afe92021-05-21 16:20:58 +0000784 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000785 pUpgradeFsm := oFsm.pAdaptFsm
786 if pUpgradeFsm != nil {
787 _ = pUpgradeFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
788 return
789 }
790 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000791 return
792 }
793 framePrint = false //for the next Section frame (if wanted, can be enabled in logic before sendXXX())
794 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000795 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000796 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenkoaa3afe92021-05-21 16:20:58 +0000797 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko59498c12021-03-18 14:15:15 +0000798 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenkoaa3afe92021-05-21 16:20:58 +0000799 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000800 }
801 }
mpagenko9c225032021-10-15 14:26:49 +0000802} //runSwDlSectionWindow
mpagenko80622a52021-02-09 16:53:23 +0000803
804func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
805 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
806 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
807}
808
809func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000810 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000811 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
mpagenko80622a52021-02-09 16:53:23 +0000812
mpagenkoaa3afe92021-05-21 16:20:58 +0000813 oFsm.mutexUpgradeParams.RLock()
mpagenko80622a52021-02-09 16:53:23 +0000814 if oFsm.delayEndSwDl {
mpagenkoaa3afe92021-05-21 16:20:58 +0000815 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000816 //give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
817 // should not be set in case this state is used for real download abort (not yet implemented)
818 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoaa3afe92021-05-21 16:20:58 +0000819 } else {
820 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000821 }
822
mpagenko59498c12021-03-18 14:15:15 +0000823 pBaseFsm := oFsm.pAdaptFsm
824 if pBaseFsm == nil {
mpagenko9c225032021-10-15 14:26:49 +0000825 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
826 oFsm.mutexUpgradeParams.Lock()
827 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
828 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000829 // Can't call FSM Event directly, decoupling it
830 go func(a_pAFsm *AdapterFsm) {
831 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
832 }(pBaseFsm)
833 return
834 }
mpagenko9c225032021-10-15 14:26:49 +0000835 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko59498c12021-03-18 14:15:15 +0000836 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.origImageLength, oFsm.imageCRC)
mpagenko80622a52021-02-09 16:53:23 +0000837 if err != nil {
mpagenko9c225032021-10-15 14:26:49 +0000838 logger.Errorw(ctx, "EndSwDl abort: error sending EndSwDl", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000839 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000840 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000841 return
842 }
mpagenko59498c12021-03-18 14:15:15 +0000843 // go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
844 // Can't call FSM Event directly, decoupling it
845 go func(a_pAFsm *AdapterFsm) {
846 _ = a_pAFsm.pFsm.Event(upgradeEvWaitEndDownload)
847 }(pBaseFsm)
848}
849
850func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
851 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
852 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
853 if oFsm.waitCountEndSwDl == 0 {
854 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
855 "device-id": oFsm.deviceID})
856 pBaseFsm := oFsm.pAdaptFsm
857 if pBaseFsm == nil {
858 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
859 "device-id": oFsm.deviceID})
860 return
861 }
mpagenko9c225032021-10-15 14:26:49 +0000862 oFsm.mutexUpgradeParams.Lock()
863 oFsm.isEndSwDlOpen = false //no need to additionally request abort of download (already finished)
864 oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
865 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000866 go func(a_pAFsm *AdapterFsm) {
867 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
868 }(pBaseFsm)
869 return
870 }
871
872 oFsm.waitCountEndSwDl--
873 select {
874 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
875 pBaseFsm := oFsm.pAdaptFsm
876 if pBaseFsm == nil {
877 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
878 "device-id": oFsm.deviceID})
879 //FSM may be reset already from somewhere else, nothing we can do here anymore
880 return
881 }
882 //retry End SW DL
mpagenkoaa3afe92021-05-21 16:20:58 +0000883 oFsm.mutexUpgradeParams.Lock()
mpagenko59498c12021-03-18 14:15:15 +0000884 oFsm.delayEndSwDl = false //no more extra delay for the request
mpagenkoaa3afe92021-05-21 16:20:58 +0000885 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000886 go func(a_pAFsm *AdapterFsm) {
887 _ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
888 }(pBaseFsm)
889 return
890 case success := <-oFsm.chReceiveExpectedResponse:
891 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +0000892 oFsm.isEndSwDlOpen = false //no request to abort of download (already finished or immediate abort)
mpagenko59498c12021-03-18 14:15:15 +0000893 pBaseFsm := oFsm.pAdaptFsm
894 if pBaseFsm == nil {
895 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
896 "device-id": oFsm.deviceID})
897 //FSM may be reset already from somewhere else, nothing we can do here anymore
898 return
899 }
900 if success {
901 //answer received with ready indication
mpagenko9c225032021-10-15 14:26:49 +0000902 //useAPIVersion43 may not conflict in concurrency in this state function
903 if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
mpagenkoc26d4c02021-05-06 14:27:57 +0000904 go func(a_pAFsm *AdapterFsm) {
mpagenko9c225032021-10-15 14:26:49 +0000905 _ = a_pAFsm.pFsm.Event(upgradeEvCheckImageName)
mpagenkoc26d4c02021-05-06 14:27:57 +0000906 }(pBaseFsm)
mpagenko9c225032021-10-15 14:26:49 +0000907 } else { // elder API usage does not support image version check -immediately consider download as successful
908 if oFsm.activateImage {
909 //immediate activation requested
910 go func(a_pAFsm *AdapterFsm) {
911 _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
912 }(pBaseFsm)
913 } else {
914 //have to wait on explicit activation request
915 go func(a_pAFsm *AdapterFsm) {
916 _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
917 }(pBaseFsm)
918 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000919 }
mpagenko59498c12021-03-18 14:15:15 +0000920 return
921 }
922 //timer was aborted
mpagenko9c225032021-10-15 14:26:49 +0000923 oFsm.abortOnOmciError(ctx, true)
mpagenko59498c12021-03-18 14:15:15 +0000924 return
925 }
mpagenko80622a52021-02-09 16:53:23 +0000926}
927
mpagenko9c225032021-10-15 14:26:49 +0000928func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
929 logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
930 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
931 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
932 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
933 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
934 false, oFsm.pAdaptFsm.commChan)
935 if err != nil {
936 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
937 log.Fields{"device-id": oFsm.deviceID, "Error": err})
938 oFsm.abortOnOmciError(ctx, true)
939 return
940 }
941 oFsm.pLastTxMeInstance = meInstance
942}
943
mpagenko80622a52021-02-09 16:53:23 +0000944func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
945 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
946 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
947
mpagenkoaa3afe92021-05-21 16:20:58 +0000948 oFsm.mutexUpgradeParams.Lock()
949 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
950 oFsm.mutexUpgradeParams.Unlock()
951
mpagenko9c225032021-10-15 14:26:49 +0000952 err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000953 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
954 if err != nil {
955 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
956 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000957 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000958 return
959 }
mpagenko9c225032021-10-15 14:26:49 +0000960 oFsm.mutexUpgradeParams.Lock()
961 oFsm.upgradePhase = cUpgradeActivating //start of image activation for ONU
962 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
963 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000964}
965
966func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko9c225032021-10-15 14:26:49 +0000967 logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
968 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
969 //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
970 // (which is a bit problematic as the ONU might already be in committed state,
971 // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
972 if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
mpagenkoaa3afe92021-05-21 16:20:58 +0000973 oFsm.mutexUpgradeParams.Lock()
mpagenko9c225032021-10-15 14:26:49 +0000974 if activeImageID == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +0000975 inactiveImageID := oFsm.inactiveImageMeID
mpagenko15ff4a52021-03-02 10:09:20 +0000976 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
mpagenkoaa3afe92021-05-21 16:20:58 +0000977 "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
978 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
mpagenko9c225032021-10-15 14:26:49 +0000979 oFsm.upgradePhase = cUpgradeCommitting //start of image commitment for ONU
mpagenkoaa3afe92021-05-21 16:20:58 +0000980 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000981 err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenkoaa3afe92021-05-21 16:20:58 +0000982 oFsm.pAdaptFsm.commChan, inactiveImageID) //more efficient activeImageID with above check
mpagenko15ff4a52021-03-02 10:09:20 +0000983 if err != nil {
984 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
985 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000986 oFsm.abortOnOmciError(ctx, true)
mpagenko15ff4a52021-03-02 10:09:20 +0000987 return
988 }
989 return
990 }
mpagenko9c225032021-10-15 14:26:49 +0000991 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000992 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
993 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
mpagenko9c225032021-10-15 14:26:49 +0000994 } else {
995 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
996 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000997 }
mpagenko9c225032021-10-15 14:26:49 +0000998 oFsm.mutexUpgradeParams.Lock()
999 oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
1000 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1001 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001002 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1003 pBaseFsm := oFsm.pAdaptFsm
1004 // Can't call FSM Event directly, decoupling it
1005 go func(a_pAFsm *AdapterFsm) {
1006 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
1007 }(pBaseFsm)
1008}
1009
1010func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
mpagenko9c225032021-10-15 14:26:49 +00001011 logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +00001012 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
mpagenko15ff4a52021-03-02 10:09:20 +00001013 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
mpagenko9c225032021-10-15 14:26:49 +00001014 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra0b235842021-03-09 13:06:46 -08001015 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
mpagenko15ff4a52021-03-02 10:09:20 +00001016 //accept also nil as (error) return value for writing to LastTx
1017 // - this avoids misinterpretation of new received OMCI messages
ozgecanetsiab36ed572021-04-01 10:38:48 +03001018 if err != nil {
1019 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
1020 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko9c225032021-10-15 14:26:49 +00001021 oFsm.abortOnOmciError(ctx, true)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001022 return
1023 }
mpagenko15ff4a52021-03-02 10:09:20 +00001024 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +00001025}
1026
1027func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1028 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
1029
mpagenko9c225032021-10-15 14:26:49 +00001030 oFsm.stateUpdateOnReset(ctx)
1031
1032 oFsm.mutexAbortRequest.Lock()
1033 //to be sure to abort a possibly still running runSwDlSectionWindow()
1034 // in case the reset was not received from cancel() and download not finished correctly
1035 oFsm.abortRequested = oFsm.volthaDownloadReason
1036 oFsm.mutexAbortRequest.Unlock()
1037
mpagenkoc26d4c02021-05-06 14:27:57 +00001038 // in case the download-to-ONU timer is still running - cancel it
mpagenko9c225032021-10-15 14:26:49 +00001039 //use non-blocking channel (to be independent from receiver state)
1040 select {
1041 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1042 case oFsm.chOnuDlReady <- false:
1043 default:
1044 }
1045 pConfigUpgradeStateAFsm := oFsm.pAdaptFsm
1046 if pConfigUpgradeStateAFsm != nil {
1047 var nextEvent string
1048 if oFsm.isEndSwDlOpen {
1049 if oFsm.repeatAbort {
1050 oFsm.delayEndSwDl = true //run next abort with delay
1051 } else { //initial request
1052 oFsm.delayEndSwDl = false //run next abort with no delay
1053 oFsm.waitCountEndSwDl = cWaitCountEndSwDl //init for possible repetitions
1054 }
1055 nextEvent = upgradeEvAbortSwDownload
1056 } else {
1057 nextEvent = upgradeEvRestart
1058 }
1059 // Can't call FSM Event directly, decoupling it
1060 go func(a_pAFsm *AdapterFsm) {
1061 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1062 _ = a_pAFsm.pFsm.Event(nextEvent)
1063 }
1064 }(pConfigUpgradeStateAFsm)
1065 }
1066}
1067
1068func (oFsm *OnuUpgradeFsm) enterAbortingDL(ctx context.Context, e *fsm.Event) {
1069 logger.Debugw(ctx, "OnuUpgradeFsm aborting download to ONU", log.Fields{"device-id": oFsm.deviceID})
1070
1071 oFsm.mutexUpgradeParams.RLock()
1072 if oFsm.delayEndSwDl {
1073 oFsm.mutexUpgradeParams.RUnlock()
1074 //give the ONU some time for image discard activities
1075 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoc26d4c02021-05-06 14:27:57 +00001076 } else {
mpagenko9c225032021-10-15 14:26:49 +00001077 oFsm.mutexUpgradeParams.RUnlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001078 }
1079
mpagenko9c225032021-10-15 14:26:49 +00001080 pBaseFsm := oFsm.pAdaptFsm
1081 if pBaseFsm == nil {
1082 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
1083 return
1084 }
1085 // abort the download operation by sending an end software download message with invalid CRC and image size
1086 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx),
1087 oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
1088 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, 0, 0xFFFFFFFF)
1089 if err != nil {
1090 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: can't send EndSwDl request", log.Fields{"device-id": oFsm.deviceID})
1091 // Can't call FSM Event directly, decoupling it
1092 go func(a_pAFsm *AdapterFsm) {
1093 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1094 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1095 }
1096 }(pBaseFsm)
1097 return
1098 }
1099
1100 //avoid waiting in the enterXXX function here,
1101 // otherwise synchronous event calls (like from RxMessage processing) may block and block complete Rx processing then
1102 go oFsm.waitOnAbortEndSwDlResponse(ctx)
1103}
1104
1105//abortingDlEvaluateResponse waits for a channel indication with decision to proceed the FSM processing
1106func (oFsm *OnuUpgradeFsm) abortingDlEvaluateResponse(ctx context.Context,
1107 pBaseFsm *AdapterFsm, aResponseResult tEndSwDlResponseResult) bool {
1108 switch aResponseResult {
1109 case cEndSwDlResponseBusy: // indication for device busy, needs repetition
1110 if oFsm.waitCountEndSwDl == 0 {
1111 logger.Errorw(ctx, "aborting download: max limit of EndSwDl reached", log.Fields{
1112 "device-id": oFsm.deviceID})
1113 go func(a_pAFsm *AdapterFsm) {
1114 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1115 _ = a_pAFsm.pFsm.Event(upgradeEvRestart) //give up and let FSM terminate
1116 }
1117 }(pBaseFsm)
1118 } else {
1119 logger.Debugw(ctx, "aborting download: re-trigger sending abort SwDl", log.Fields{
1120 "device-id": oFsm.deviceID, "counter": oFsm.waitCountEndSwDl})
1121 oFsm.waitCountEndSwDl--
1122 oFsm.repeatAbort = true //repeated request in next round
1123 go func(a_pAFsm *AdapterFsm) {
1124 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1125 _ = a_pAFsm.pFsm.Event(upgradeEvReset) //which then re-triggers sending AbortSwDL
1126 }
1127 }(pBaseFsm)
1128 }
1129 return true
1130 case cEndSwDlResponseSuccess: // indication for success response
1131 logger.Infow(ctx, "aborting download: success response, terminating FSM", log.Fields{
1132 "device-id": oFsm.deviceID})
1133 case cEndSwDlResponseAbort: // indication for request to abort waiting for response
1134 logger.Infow(ctx, "aborting download: request to abort waiting, terminating FSM", log.Fields{
1135 "device-id": oFsm.deviceID})
1136 default:
1137 logger.Errorw(ctx, "aborting download: unknown channel indication, terminating FSM", log.Fields{
1138 "device-id": oFsm.deviceID})
1139 } //switch
1140 return false
1141}
1142
1143func (oFsm *OnuUpgradeFsm) enterRestarting(ctx context.Context, e *fsm.Event) {
1144 logger.Debugw(ctx, "OnuUpgradeFsm restarting", log.Fields{"device-id": oFsm.deviceID})
1145 pConfigUpgradeStateAFsm := oFsm.pAdaptFsm
1146 if pConfigUpgradeStateAFsm != nil {
mpagenko80622a52021-02-09 16:53:23 +00001147 // abort running message processing
1148 fsmAbortMsg := Message{
1149 Type: TestMsg,
1150 Data: TestMessage{
1151 TestMessageVal: AbortMessageProcessing,
1152 },
1153 }
mpagenko9c225032021-10-15 14:26:49 +00001154 pConfigUpgradeStateAFsm.commChan <- fsmAbortMsg
mpagenko80622a52021-02-09 16:53:23 +00001155
1156 //try to restart the FSM to 'disabled'
1157 // Can't call FSM Event directly, decoupling it
1158 go func(a_pAFsm *AdapterFsm) {
1159 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko9c225032021-10-15 14:26:49 +00001160 _ = a_pAFsm.pFsm.Event(upgradeEvDisable)
mpagenko80622a52021-02-09 16:53:23 +00001161 }
mpagenko9c225032021-10-15 14:26:49 +00001162 }(pConfigUpgradeStateAFsm)
mpagenko80622a52021-02-09 16:53:23 +00001163 }
1164}
1165
1166func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1167 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001168 // 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 +00001169 if oFsm.pDeviceHandler != nil {
1170 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenko9c225032021-10-15 14:26:49 +00001171 pLastUpgradeImageState := &voltha.ImageState{
1172 Version: oFsm.imageVersion,
1173 DownloadState: oFsm.volthaDownloadState,
1174 Reason: oFsm.volthaDownloadReason,
1175 ImageState: oFsm.volthaImageState,
1176 }
1177 go oFsm.pDeviceHandler.RemoveOnuUpgradeFsm(ctx, pLastUpgradeImageState)
mpagenko80622a52021-02-09 16:53:23 +00001178 }
1179}
1180
1181func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
1182 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
1183loop:
1184 for {
1185 // case <-ctx.Done():
1186 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
1187 // break loop
1188 message, ok := <-oFsm.pAdaptFsm.commChan
1189 if !ok {
1190 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
1191 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko9c225032021-10-15 14:26:49 +00001192 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +00001193 break loop
1194 }
1195 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
1196
1197 switch message.Type {
1198 case TestMsg:
1199 msg, _ := message.Data.(TestMessage)
1200 if msg.TestMessageVal == AbortMessageProcessing {
1201 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
1202 break loop
1203 }
1204 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
1205 case OMCI:
1206 msg, _ := message.Data.(OmciMessage)
1207 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
1208 default:
1209 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
1210 "message.Type": message.Type})
1211 }
1212 }
1213 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
1214}
1215
mpagenko80622a52021-02-09 16:53:23 +00001216func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg OmciMessage) {
1217 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
1218 "msgType": msg.OmciMsg.MessageType})
1219
1220 switch msg.OmciMsg.MessageType {
1221 case omci.StartSoftwareDownloadResponseType:
1222 {
mpagenko9c225032021-10-15 14:26:49 +00001223 oFsm.handleRxStartSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001224 return
1225 } //StartSoftwareDownloadResponseType
1226 case omci.DownloadSectionResponseType:
1227 {
mpagenko9c225032021-10-15 14:26:49 +00001228 oFsm.handleRxSwSectionResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001229 return
mpagenko80622a52021-02-09 16:53:23 +00001230 } //DownloadSectionResponseType
1231 case omci.EndSoftwareDownloadResponseType:
1232 {
mpagenko9c225032021-10-15 14:26:49 +00001233 oFsm.handleRxEndSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001234 return
1235 } //EndSoftwareDownloadResponseType
1236 case omci.ActivateSoftwareResponseType:
1237 {
1238 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1239 if msgLayer == nil {
1240 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1241 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001242 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001243 return
1244 }
1245 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1246 if !msgOk {
1247 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1248 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001249 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001250 return
1251 }
1252 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1253 "device-id": oFsm.deviceID, "data-fields": msgObj})
1254 if msgObj.Result != me.Success {
1255 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1256 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko9c225032021-10-15 14:26:49 +00001257 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001258 return
1259 }
mpagenko183647c2021-06-08 15:25:04 +00001260 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001261 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko9c225032021-10-15 14:26:49 +00001262 // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
mpagenko183647c2021-06-08 15:25:04 +00001263 oFsm.mutexUpgradeParams.Unlock()
1264 logger.Infow(ctx, "Expected ActivateSwResponse received",
1265 log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
1266 if oFsm.commitImage {
1267 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
1268 } else {
1269 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvActivationDone) // let the FSM wait for external commit request
1270 }
mpagenko80622a52021-02-09 16:53:23 +00001271 return
1272 }
mpagenko183647c2021-06-08 15:25:04 +00001273 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001274 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1275 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko9c225032021-10-15 14:26:49 +00001276 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001277 return
1278 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001279 case omci.CommitSoftwareResponseType:
1280 {
1281 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1282 if msgLayer == nil {
1283 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1284 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001285 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001286 return
1287 }
1288 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1289 if !msgOk {
1290 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1291 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001292 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001293 return
1294 }
mpagenkobf67a092021-03-17 09:52:28 +00001295 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001296 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1297 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko9c225032021-10-15 14:26:49 +00001298 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001299 return
mpagenkobf67a092021-03-17 09:52:28 +00001300 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001301 oFsm.mutexUpgradeParams.RLock()
mpagenko15ff4a52021-03-02 10:09:20 +00001302 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001303 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001304 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1305 //verifying committed image
1306 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
1307 return
1308 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001309 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001310 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1311 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko9c225032021-10-15 14:26:49 +00001312 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001313 return
1314 } //CommitSoftwareResponseType
1315 case omci.GetResponseType:
1316 {
mpagenko9c225032021-10-15 14:26:49 +00001317 oFsm.handleRxSwGetResponse(ctx, msg)
mpagenko15ff4a52021-03-02 10:09:20 +00001318 return
1319 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001320 default:
1321 {
1322 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1323 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1324 return
1325 }
1326 }
1327}
1328
mpagenko9c225032021-10-15 14:26:49 +00001329func (oFsm *OnuUpgradeFsm) handleRxStartSwDownloadResponse(ctx context.Context, msg OmciMessage) {
1330 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
1331 if msgLayer == nil {
1332 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
1333 log.Fields{"device-id": oFsm.deviceID})
1334 oFsm.abortOnOmciError(ctx, false)
1335 return
1336 }
1337 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
1338 if !msgOk {
1339 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
1340 log.Fields{"device-id": oFsm.deviceID})
1341 oFsm.abortOnOmciError(ctx, false)
1342 return
1343 }
1344 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
1345 "device-id": oFsm.deviceID, "data-fields": msgObj})
1346 if msgObj.Result != me.Success {
1347 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
1348 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1349 oFsm.abortOnOmciError(ctx, false)
1350 return
1351 }
1352
1353 oFsm.mutexUpgradeParams.Lock()
1354 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1355 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1356 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
1357 // also response WindowSize = 0 is a valid number for used Window size 1
1358 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
1359 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
1360 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
1361 }
1362 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
1363 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
1364 oFsm.noOfWindows++
1365 }
1366 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
1367 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
1368 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
1369 oFsm.nextDownloadSectionsAbsolute = 0
1370 oFsm.nextDownloadSectionsWindow = 0
1371 oFsm.nextDownloadWindow = 0
1372
1373 oFsm.mutexUpgradeParams.Unlock()
1374 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
1375 return
1376 }
1377 oFsm.mutexUpgradeParams.Unlock()
1378 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1379 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1380 oFsm.abortOnOmciError(ctx, false)
1381} //handleRxStartSwDownloadResponse
1382
1383func (oFsm *OnuUpgradeFsm) handleRxSwSectionResponse(ctx context.Context, msg OmciMessage) {
1384 if oFsm.pAdaptFsm == nil {
1385 logger.Infow(ctx, "DlSectionResponse received - but FSM not really valid anymore", log.Fields{
1386 "device-id": oFsm.deviceID})
1387 return
1388 }
1389 if !oFsm.pAdaptFsm.pFsm.Is(upgradeStVerifyWindow) {
1390 //all the processing here is only relevant if the FSM is in state upgradeStVerifyWindow
1391 // otherwise this response can be ignored (may stem from a long-processing window send activity,
1392 // which is not anymore relevant based on intermediate (cancel) state transitions)
1393 logger.Infow(ctx, "DlSectionResponse received - but ignored", log.Fields{
1394 "device-id": oFsm.deviceID, "fsm-state": oFsm.pAdaptFsm.pFsm.Current()})
1395 return
1396 }
1397 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
1398 if msgLayer == nil {
1399 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
1400 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
1401 oFsm.abortOnOmciError(ctx, false)
1402 return
1403 }
1404 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
1405 if !msgOk {
1406 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
1407 log.Fields{"device-id": oFsm.deviceID})
1408 oFsm.abortOnOmciError(ctx, false)
1409 return
1410 }
1411 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
1412 "device-id": oFsm.deviceID, "data-fields": msgObj})
1413 if msgObj.Result != me.Success {
1414 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
1415 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1416 oFsm.abortOnOmciError(ctx, false)
1417 return
1418 }
1419 oFsm.mutexUpgradeParams.Lock()
1420 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1421 sectionNumber := msgObj.SectionNumber
1422 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
1423 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
1424
1425 oFsm.nextDownloadWindow++
1426 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
1427 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
1428 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
1429 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
1430 "expected section": oFsm.omciDownloadWindowSizeLast})
1431 oFsm.mutexUpgradeParams.Unlock()
1432 oFsm.abortOnOmciError(ctx, false)
1433 return
1434 }
1435 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
1436 //CRC computation for all data bytes of the file
1437 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
1438 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
1439 var byteSlice []byte = make([]byte, 4)
1440 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
1441 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
1442 oFsm.mutexUpgradeParams.Unlock()
1443 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
1444 return
1445 }
1446 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
1447 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
1448 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
1449 "expected section": oFsm.omciDownloadWindowSizeLimit})
1450 oFsm.mutexUpgradeParams.Unlock()
1451 oFsm.abortOnOmciError(ctx, false)
1452 return
1453 }
1454 oFsm.nextDownloadSectionsWindow = 0
1455 oFsm.mutexUpgradeParams.Unlock()
1456 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
1457 return
1458 }
1459 oFsm.mutexUpgradeParams.Unlock()
1460 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1461 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1462 oFsm.abortOnOmciError(ctx, false)
1463} //handleRxSwSectionResponse
1464
1465func (oFsm *OnuUpgradeFsm) handleRxEndSwDownloadResponse(ctx context.Context, msg OmciMessage) {
1466 inAbortingState := oFsm.pAdaptFsm.pFsm.Is(upgradeStAbortingDL)
1467
1468 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1469 if msgLayer == nil {
1470 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1471 log.Fields{"device-id": oFsm.deviceID})
1472 if !inAbortingState {
1473 oFsm.abortOnOmciError(ctx, false)
1474 } //else using error log and wait for another response or 'aborting' state timeout
1475 return
1476 }
1477 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1478 if !msgOk {
1479 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1480 log.Fields{"device-id": oFsm.deviceID})
1481 if !inAbortingState {
1482 oFsm.abortOnOmciError(ctx, false)
1483 } //else using error log and wait for another response or 'aborting' state timeout
1484 return
1485 }
1486 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1487 "device-id": oFsm.deviceID, "data-fields": msgObj})
1488 if msgObj.Result != me.Success {
1489 if msgObj.Result == me.DeviceBusy {
1490 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1491 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1492 "device-id": oFsm.deviceID})
1493 if inAbortingState {
1494 //if the EndSwDl was requested from state AbortingDL then use channel to indicate ONU busy/repeat indication
1495 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseBusy //repeat abort request
1496 }
1497 oFsm.mutexUpgradeParams.Lock()
1498 oFsm.downloadReasonCached = oFsm.volthaDownloadReason //copy for later reconstruction
1499 oFsm.volthaDownloadReason = voltha.ImageState_DEVICE_BUSY
1500 oFsm.mutexUpgradeParams.Unlock()
1501 return
1502 }
1503 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
1504 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1505 if inAbortingState {
1506 //if the EndSwDl was requested from state AbortingDL and response is error indication
1507 // that would be quite strange ONU behavior, no resolution from OnuAdapter, just let the FSM go on to disabled
1508 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //error indication to abort waiting on EndDownloadResponse
1509 } //else using error log and wait for another response or 'aborting' state timeout
1510 return
1511 }
1512 oFsm.mutexUpgradeParams.Lock()
1513 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1514 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1515 if oFsm.volthaDownloadReason == voltha.ImageState_DEVICE_BUSY { //was temporary on busy
1516 oFsm.volthaDownloadReason = oFsm.downloadReasonCached //recapture from mirror
1517 }
1518 if inAbortingState {
1519 oFsm.mutexUpgradeParams.Unlock()
1520 //if the EndSwDl was requested from state AbortingDL then use channel to indicate abort acceptance
1521 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseSuccess //success
1522 return
1523 }
1524 if !oFsm.useAPIVersion43 {
1525 //in the older API version the image version check was not possible
1526 // - assume new loaded image as valid-inactive immediately
1527 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1528 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1529 oFsm.mutexUpgradeParams.Unlock()
1530 //use non-blocking channel (to be independent from receiver state)
1531 select {
1532 //use non-blocking channel to indicate that the download to ONU was successful
1533 case oFsm.chOnuDlReady <- true:
1534 default:
1535 }
1536 } else {
1537 oFsm.mutexUpgradeParams.Unlock()
1538 }
1539 //use asynchronous channel sending to let the FSM proceed
1540 select {
1541 case oFsm.chReceiveExpectedResponse <- true:
1542 default:
1543 }
1544 return
1545 }
1546 oFsm.mutexUpgradeParams.Unlock()
1547 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: ignoring",
1548 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1549 // no state abort in case of unexpected ImageId, just keep waiting for the correct one
1550} //handleRxEndSwDownloadResponse
1551
1552func (oFsm *OnuUpgradeFsm) handleRxSwGetResponse(ctx context.Context, msg OmciMessage) {
1553 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1554 if msgLayer == nil {
1555 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1556 log.Fields{"device-id": oFsm.deviceID})
1557 oFsm.abortOnOmciError(ctx, false)
1558 return
1559 }
1560 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1561 if !msgOk {
1562 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1563 log.Fields{"device-id": oFsm.deviceID})
1564 oFsm.abortOnOmciError(ctx, false)
1565 return
1566 }
1567 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1568 "device-id": oFsm.deviceID, "data-fields": msgObj})
1569 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1570 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1571 if msgObj.Result != me.Success {
1572 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1573 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1574 oFsm.abortOnOmciError(ctx, false)
1575 return
1576 }
1577 } else {
1578 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1579 log.Fields{"device-id": oFsm.deviceID})
1580 return
1581 }
1582
1583 meAttributes := msgObj.Attributes
1584 imageIsCommitted := meAttributes["IsCommitted"].(uint8)
1585 imageIsActive := meAttributes["IsActive"].(uint8)
1586 imageVersion := TrimStringFromMeOctet(meAttributes["Version"])
1587 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
1588 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1589 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
1590
1591 if oFsm.pAdaptFsm.pFsm.Current() == upgradeStCheckImageName {
1592 //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
1593 oFsm.verifyOnuSwStatusAfterDownload(ctx, msgObj.EntityInstance, imageVersion, imageIsActive, imageIsCommitted)
1594 return
1595 }
1596
1597 //assumed only relevant state here is upgradeStCheckCommitted
1598 oFsm.mutexUpgradeParams.Lock()
1599 oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
1600 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive {
1601 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1602 // indicated in the download image version string (version must be part of the image content itself)
1603 // so checking that might be quite unreliable
1604 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1605 // in all the API references, so it can and should be checked here now
1606 if oFsm.useAPIVersion43 {
1607 if imageVersion != oFsm.imageVersion {
1608 //new active version indicated on OMCI from ONU is not the expected version
1609 logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
1610 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1611 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1612 // TODO!!!: error treatment?
1613 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1614 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1615 oFsm.mutexUpgradeParams.Unlock()
1616 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1617 return
1618 }
1619 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1620 log.Fields{"device-id": oFsm.deviceID})
1621 }
1622 if imageIsCommitted == swIsCommitted {
1623 oFsm.upgradePhase = cUpgradeCommitted
1624 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
1625 //store the new commit flag to onuSwImageIndications (to keep them in sync)
1626 oFsm.pDevEntry.ModifySwImageActiveCommit(ctx, imageIsCommitted)
1627 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
1628 //deviceProcStatusUpdate not used anymore,
1629 // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
1630 oFsm.mutexUpgradeParams.Unlock()
1631 //releasing the upgrade FSM on success
1632 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1633 return
1634 }
1635 //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
1636 }
1637 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1638 oFsm.mutexUpgradeParams.Unlock()
1639 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1640 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1641 // TODO!!!: error treatment?
1642 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1643 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1644} //handleRxSwGetResponse
1645
1646func (oFsm *OnuUpgradeFsm) verifyOnuSwStatusAfterDownload(ctx context.Context, aInstanceID uint16,
1647 aImageVersion string, aImageIsActive uint8, aImageIsCommitted uint8) {
1648 oFsm.mutexUpgradeParams.Lock()
1649 if aInstanceID == oFsm.inactiveImageMeID && aImageIsActive == swIsInactive &&
1650 aImageIsCommitted == swIsUncommitted {
1651 if aImageVersion != oFsm.imageVersion {
1652 //new stored inactive version indicated on OMCI from ONU is not the expected version
1653 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
1654 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID,
1655 "onu-version": aImageVersion, "expected-version": oFsm.imageVersion})
1656 //download state is set when entering the reset state
1657 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1658 oFsm.mutexUpgradeParams.Unlock()
1659 //stop the running ONU download timer
1660 //use non-blocking channel (to be independent from receiver state)
1661 select {
1662 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1663 case oFsm.chOnuDlReady <- false:
1664 default:
1665 }
1666 // TODO!!!: error treatment?
1667 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1668 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1669 return
1670 }
1671 //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
1672 oFsm.upgradePhase = cUpgradeDownloaded
1673 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1674 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1675 //store the new inactive version to onuSwImageIndications (to keep them in sync)
1676 oFsm.pDevEntry.ModifySwImageInactiveVersion(ctx, oFsm.imageVersion)
1677 //proceed within upgrade FSM
1678 if oFsm.activateImage {
1679 //immediate activation requested
1680 oFsm.mutexUpgradeParams.Unlock()
1681 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
1682 log.Fields{"device-id": oFsm.deviceID})
1683 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRequestActivate)
1684 } else {
1685 //have to wait on explicit activation request
1686 oFsm.mutexUpgradeParams.Unlock()
1687 logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
1688 log.Fields{"device-id": oFsm.deviceID})
1689 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForActivate)
1690 }
1691 //use non-blocking channel (to be independent from receiver state)
1692 select {
1693 //use non-blocking channel to indicate that the download to ONU was successful
1694 case oFsm.chOnuDlReady <- true:
1695 default:
1696 }
1697 return
1698 }
1699 //not the expected image/image state
1700 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1701 oFsm.mutexUpgradeParams.Unlock()
1702 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1703 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID})
1704 // TODO!!!: error treatment?
1705 //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
1706 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1707} //verifyOnuSwStatusAfterDownload
1708
1709//abortOnOmciError aborts the upgrade processing with evAbort
1710// asynchronous/synchronous based on parameter aAsync
1711func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool) {
1712 oFsm.mutexUpgradeParams.Lock()
1713 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1714 oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
1715 oFsm.mutexUpgradeParams.Unlock()
1716 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1717 if oFsm.pAdaptFsm != nil {
1718 var err error
1719 if aAsync { //asynchronous call requested to ensure state transition
1720 go func(a_pAFsm *AdapterFsm) {
1721 if a_pAFsm.pFsm != nil {
1722 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1723 }
1724 }(oFsm.pAdaptFsm)
1725 } else {
1726 if oFsm.pAdaptFsm.pFsm != nil {
1727 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1728 }
1729 }
1730 if err != nil {
1731 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1732 "device-id": oFsm.deviceID, "error": err})
1733 }
1734 }
1735}
1736
mpagenkoc26d4c02021-05-06 14:27:57 +00001737//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
mpagenko9c225032021-10-15 14:26:49 +00001738// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
1739func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
1740 aWaitChannel chan bool) {
mpagenkoc26d4c02021-05-06 14:27:57 +00001741 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
mpagenko9c225032021-10-15 14:26:49 +00001742 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
mpagenkoc26d4c02021-05-06 14:27:57 +00001743 oFsm.isWaitingForAdapterDlResponse = true
1744 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko9c225032021-10-15 14:26:49 +00001745 aSyncChannel <- struct{}{}
mpagenko80622a52021-02-09 16:53:23 +00001746 select {
1747 // maybe be also some outside cancel (but no context modeled for the moment ...)
1748 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001749 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1750 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1751 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1752 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1753 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
mpagenko9c225032021-10-15 14:26:49 +00001754 //running into timeout here may still have the download to adapter active -> abort
1755 oFsm.pFileManager.CancelDownload(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +00001756 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1757 oFsm.isWaitingForAdapterDlResponse = false
1758 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko9c225032021-10-15 14:26:49 +00001759 oFsm.mutexUpgradeParams.Lock()
1760 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1761 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'DOWNLOAD_TO_ADAPTER_TIMEOUT' would be better (proto)
1762 oFsm.mutexUpgradeParams.Unlock()
1763 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1764 if oFsm.pAdaptFsm != nil && oFsm.pAdaptFsm.pFsm != nil {
1765 err := oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1766 if err != nil {
1767 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1768 "device-id": oFsm.deviceID, "error": err})
1769 }
mpagenko80622a52021-02-09 16:53:23 +00001770 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001771 return
1772
1773 case success := <-aWaitChannel:
1774 if success {
1775 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1776 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1777 oFsm.isWaitingForAdapterDlResponse = false
1778 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1779 //let the upgrade process proceed
1780 pUpgradeFsm := oFsm.pAdaptFsm
1781 if pUpgradeFsm != nil {
1782 _ = pUpgradeFsm.pFsm.Event(upgradeEvPrepareSwDownload)
1783 } else {
1784 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1785 }
1786 return
1787 }
mpagenko9c225032021-10-15 14:26:49 +00001788 // waiting was aborted (assumed here to be caused by
1789 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001790 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1791 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1792 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1793 oFsm.isWaitingForAdapterDlResponse = false
1794 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001795 return
mpagenko80622a52021-02-09 16:53:23 +00001796 }
1797}
mpagenkoc26d4c02021-05-06 14:27:57 +00001798
1799//waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1800func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1801 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1802 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1803 "duration": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001804 select {
1805 // maybe be also some outside cancel (but no context modeled for the moment ...)
1806 // case <-ctx.Done():
1807 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1808 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1809 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1810 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001811 //the upgrade process has to be aborted
mpagenko9c225032021-10-15 14:26:49 +00001812 oFsm.abortOnOmciError(ctx, false)
mpagenkoc26d4c02021-05-06 14:27:57 +00001813 return
1814
1815 case success := <-aWaitChannel:
1816 if success {
1817 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001818 //all fine, let the FSM proceed like defined from the sender of this event
1819 return
1820 }
1821 // waiting was aborted (assumed here to be caused by
mpagenko9c225032021-10-15 14:26:49 +00001822 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001823 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001824 return
1825 }
1826}
mpagenko9c225032021-10-15 14:26:49 +00001827
1828//waitOnAbortEndSwDlResponse waits for either abort/success or timeout of EndSwDownload (for abortion)
1829func (oFsm *OnuUpgradeFsm) waitOnAbortEndSwDlResponse(ctx context.Context) {
1830 logger.Debugw(ctx, "OnuUpgradeFsm start wait for EndSwDl response (abort)", log.Fields{"device-id": oFsm.deviceID})
1831 select {
1832 case <-time.After(oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second):
1833 logger.Warnw(ctx, "OnuUpgradeFsm aborting download: timeout - no response received", log.Fields{"device-id": oFsm.deviceID})
1834 pUpgradeFsm := oFsm.pAdaptFsm
1835 if pUpgradeFsm != nil {
1836 _ = pUpgradeFsm.pFsm.Event(upgradeEvRestart)
1837 } else {
1838 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1839 }
1840 return
1841 case response := <-oFsm.chReceiveAbortEndSwDlResponse:
1842 logger.Debugw(ctx, "OnuUpgradeFsm aborting download: response received",
1843 log.Fields{"device-id": oFsm.deviceID, "response": response})
1844 pUpgradeFsm := oFsm.pAdaptFsm
1845 if pUpgradeFsm != nil {
1846 if oFsm.abortingDlEvaluateResponse(ctx, pUpgradeFsm, response) {
1847 return //event sent from function already
1848 }
1849 _ = pUpgradeFsm.pFsm.Event(upgradeEvRestart)
1850 } else {
1851 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1852 }
1853 return
1854 } //select
1855}
1856
1857//stateUpdateOnReset writes the download and/or image state on entering the reset state according to FSM internal indications
1858func (oFsm *OnuUpgradeFsm) stateUpdateOnReset(ctx context.Context) {
1859 oFsm.mutexUpgradeParams.Lock()
1860 defer oFsm.mutexUpgradeParams.Unlock()
1861 if !oFsm.conditionalCancelRequested {
1862 switch oFsm.upgradePhase {
1863 case cUpgradeUndefined, cUpgradeDownloading: //coming from downloading
1864 //make sure the download state is only changed in case the device has still been downloading
1865 if oFsm.volthaDownloadReason == voltha.ImageState_CANCELLED_ON_REQUEST {
1866 // indication for termination on request
1867 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
1868 } else if oFsm.volthaDownloadReason != voltha.ImageState_NO_ERROR {
1869 // indication for termination on failure
1870 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1871 }
1872 //reset the image state from Downloading in this case
1873 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1874 //in all other upgrade phases the last set download state remains valid
1875 case cUpgradeActivating:
1876 //reset the image state from Activating in this case
1877 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATION_ABORTED
1878 case cUpgradeCommitting: // indication for request to abort waiting for response
1879 //reset the image state from Activating in this case
1880 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
1881 //default: in all other upgrade phases keep the last set imageState
1882 } //switch
1883 } else {
1884 //when reaching reset state with conditional cancel that can only result from ONU related problems
1885 // (mostly ONU down indication) - derived from resetFsms call
1886 // and it can only be related to the downloading-to-ONU phase (no need to check that additionally)
1887 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1888 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1889 //reset the image state from Downloading in this case
1890 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1891 }
1892}