blob: b9b98af4ec532ccecebf14cfae68587729aa9651 [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
Holger Hildebrandta4308972022-01-21 10:55:49 +0000174 chAbortDelayEndSwDl chan struct{}
mpagenkoc26d4c02021-05-06 14:27:57 +0000175 isWaitingForAdapterDlResponse bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000176 chOnuDlReady chan bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000177 activateImage bool
178 commitImage bool
mpagenko9c225032021-10-15 14:26:49 +0000179 mutexAbortRequest sync.RWMutex
180 abortRequested voltha.ImageState_ImageFailureReason
181 conditionalCancelRequested bool
182 upgradePhase tUpgradePhase
mpagenkoaa3afe92021-05-21 16:20:58 +0000183 volthaDownloadState voltha.ImageState_ImageDownloadState
184 volthaDownloadReason voltha.ImageState_ImageFailureReason
185 volthaImageState voltha.ImageState_ImageActivationState
mpagenko9c225032021-10-15 14:26:49 +0000186 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)
Holger Hildebrandta4308972022-01-21 10:55:49 +0000215 instFsm.chAbortDelayEndSwDl = make(chan struct{})
mpagenkoc26d4c02021-05-06 14:27:57 +0000216 instFsm.chOnuDlReady = make(chan bool)
mpagenko9c225032021-10-15 14:26:49 +0000217 instFsm.chReceiveAbortEndSwDlResponse = make(chan tEndSwDlResponseResult)
mpagenko80622a52021-02-09 16:53:23 +0000218
219 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
220 if instFsm.pAdaptFsm == nil {
221 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
222 "device-id": instFsm.deviceID})
223 return nil
224 }
225 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
226 upgradeStDisabled,
227 fsm.Events{
228 {Name: upgradeEvStart, Src: []string{upgradeStDisabled}, Dst: upgradeStStarting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000229 {Name: upgradeEvAdapterDownload, Src: []string{upgradeStStarting}, Dst: upgradeStWaitingAdapterDL},
230 {Name: upgradeEvPrepareSwDownload, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL}, Dst: upgradeStPreparingDL},
mpagenko80622a52021-02-09 16:53:23 +0000231 {Name: upgradeEvRxStartSwDownload, Src: []string{upgradeStPreparingDL}, Dst: upgradeStDLSection},
232 {Name: upgradeEvWaitWindowAck, Src: []string{upgradeStDLSection}, Dst: upgradeStVerifyWindow},
233 {Name: upgradeEvContinueNextWindow, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStDLSection},
234 {Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
mpagenko59498c12021-03-18 14:15:15 +0000235 {Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
236 {Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
mpagenko9c225032021-10-15 14:26:49 +0000237 //UpgradeStCheckImageName only used with useAPIVersion43
238 {Name: upgradeEvCheckImageName, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStCheckImageName},
239 //UpgradeEvWaitForActivate state transitions depend on useAPIVersion43
240 {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL, upgradeStCheckImageName}, Dst: upgradeStWaitForActivate},
241 //UpgradeEvRequestActivate state transitions depend on useAPIVersion43
242 {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStCheckImageName,
243 upgradeStWaitForActivate}, Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
mpagenko183647c2021-06-08 15:25:04 +0000244 {Name: upgradeEvActivationDone, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStActivated},
mpagenko80622a52021-02-09 16:53:23 +0000245 {Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
mpagenko1f8e8822021-06-25 14:10:21 +0000246 {Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
247 upgradeStActivated}, Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
mpagenko15ff4a52021-03-02 10:09:20 +0000248 {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000249
250 /*
251 {Name: upgradeEvTimeoutSimple, Src: []string{
252 upgradeStCreatingDot1PMapper, upgradeStCreatingMBPCD, upgradeStSettingTconts, upgradeStSettingDot1PMapper}, Dst: upgradeStStarting},
253 {Name: upgradeEvTimeoutMids, Src: []string{
254 upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
255 */
256 // exceptional treatments
mpagenko1f8e8822021-06-25 14:10:21 +0000257 //on upgradeEvReset: upgradeStRequestingActivate, upgradeStWaitForCommit and upgradeStActivated are not reset
258 // (to let the FSM survive the expected OnuDown indication)
mpagenkoc26d4c02021-05-06 14:27:57 +0000259 {Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko9c225032021-10-15 14:26:49 +0000260 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
261 upgradeStWaitForActivate,
262 upgradeStCommitSw, upgradeStCheckCommitted, upgradeStAbortingDL},
mpagenko80622a52021-02-09 16:53:23 +0000263 Dst: upgradeStResetting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000264 {Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko9c225032021-10-15 14:26:49 +0000265 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
266 upgradeStWaitForActivate,
267 upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit,
268 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000269 Dst: upgradeStResetting},
mpagenko9c225032021-10-15 14:26:49 +0000270 {Name: upgradeEvAbortSwDownload, Src: []string{upgradeStResetting}, Dst: upgradeStAbortingDL},
271 {Name: upgradeEvRestart, Src: []string{upgradeStResetting, upgradeStAbortingDL}, Dst: upgradeStRestarting},
272 {Name: upgradeEvDisable, Src: []string{upgradeStRestarting}, Dst: upgradeStDisabled},
mpagenko80622a52021-02-09 16:53:23 +0000273 },
274 fsm.Callbacks{
275 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
276 "enter_" + upgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
mpagenkoc26d4c02021-05-06 14:27:57 +0000277 "enter_" + upgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000278 "enter_" + upgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
279 "enter_" + upgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
280 "enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
281 "enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
mpagenko59498c12021-03-18 14:15:15 +0000282 "enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
mpagenko9c225032021-10-15 14:26:49 +0000283 "enter_" + upgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000284 "enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
285 "enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
mpagenko15ff4a52021-03-02 10:09:20 +0000286 "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000287 "enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
mpagenko9c225032021-10-15 14:26:49 +0000288 "enter_" + upgradeStAbortingDL: func(e *fsm.Event) { instFsm.enterAbortingDL(ctx, e) },
289 "enter_" + upgradeStRestarting: func(e *fsm.Event) { instFsm.enterRestarting(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000290 "enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
291 },
292 )
293 if instFsm.pAdaptFsm.pFsm == nil {
294 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
295 "device-id": instFsm.deviceID})
296 return nil
297 }
298
299 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
300 return instFsm
301}
302
303//SetDownloadParams configures the needed parameters for a specific download to the ONU
mpagenkoc26d4c02021-05-06 14:27:57 +0000304// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000305func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
306 apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
mpagenko80622a52021-02-09 16:53:23 +0000307 pBaseFsm := oFsm.pAdaptFsm.pFsm
308 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000309 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000310 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
311 "device-id": oFsm.deviceID, "image-description": apImageDsc})
mpagenko15ff4a52021-03-02 10:09:20 +0000312 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000313 oFsm.pImageDsc = apImageDsc
314 oFsm.pDownloadManager = apDownloadManager
Holger Hildebrandtac1e0592021-06-03 15:16:49 +0000315 oFsm.activateImage = true
316 oFsm.commitImage = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000317 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000318
319 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000320 // let the upgrade FSM proceed to PreparingDL
mpagenko80622a52021-02-09 16:53:23 +0000321 _ = aPBaseFsm.Event(upgradeEvPrepareSwDownload)
322 }(pBaseFsm)
323 return nil
324 }
325 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
326 "device-id": oFsm.deviceID})
327 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
328}
329
mpagenkoc26d4c02021-05-06 14:27:57 +0000330//SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
331// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
332// called from 'new' API Download_onu_image
333func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
334 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *fileDownloadManager,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000335 aImageIdentifier string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000336 oFsm.mutexUpgradeParams.Lock()
337 var pBaseFsm *fsm.FSM = nil
338 if oFsm.pAdaptFsm != nil {
339 pBaseFsm = oFsm.pAdaptFsm.pFsm
340 }
341 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
342 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
343 "device-id": oFsm.deviceID, "image-description": apImageRequest})
344 oFsm.useAPIVersion43 = true
345 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
346 oFsm.pFileManager = apDownloadManager
347 oFsm.imageIdentifier = aImageIdentifier
348 oFsm.imageVersion = apImageRequest.Image.Version
349 oFsm.activateImage = apImageRequest.ActivateOnSuccess
350 oFsm.commitImage = apImageRequest.CommitOnSuccess
mpagenko9c225032021-10-15 14:26:49 +0000351 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //state change indication for download request
mpagenkoc26d4c02021-05-06 14:27:57 +0000352 oFsm.mutexUpgradeParams.Unlock()
353 _ = pBaseFsm.Event(upgradeEvAdapterDownload) //no need to call the FSM event in background here
354 return nil
355 }
356 oFsm.mutexUpgradeParams.Unlock()
357 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
358 "device-id": oFsm.deviceID})
359 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
360}
361
362//SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
363// called from 'new' API Activate_onu_image
364func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
365 aImageIdentifier string, aCommit bool) error {
mpagenko9c225032021-10-15 14:26:49 +0000366 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
367 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
mpagenkoc26d4c02021-05-06 14:27:57 +0000368 oFsm.mutexUpgradeParams.Lock()
369 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
370 // (as long as the Imageidentifier is correct)
mpagenkoc26d4c02021-05-06 14:27:57 +0000371 if aImageIdentifier != oFsm.imageIdentifier {
372 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
373 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
374 oFsm.mutexUpgradeParams.Unlock()
375 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
376 oFsm.deviceID))
377 }
378 oFsm.activateImage = true
379 oFsm.commitImage = aCommit
380 oFsm.mutexUpgradeParams.Unlock()
381 var pBaseFsm *fsm.FSM = nil
382 if oFsm.pAdaptFsm != nil {
383 pBaseFsm = oFsm.pAdaptFsm.pFsm
384 }
385 if pBaseFsm != nil {
386 if pBaseFsm.Is(upgradeStWaitForActivate) {
387 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
388 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenko9c225032021-10-15 14:26:49 +0000389 } else {
390 logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
391 "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000392 }
393 return nil
394 }
395 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
396 "device-id": oFsm.deviceID})
397 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
398}
399
400//SetActivationParamsStart starts upgrade processing with immediate activation
401// called from 'new' API Activate_onu_image
402func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
403 oFsm.mutexUpgradeParams.Lock()
404 var pBaseFsm *fsm.FSM = nil
405 if oFsm.pAdaptFsm != nil {
406 pBaseFsm = oFsm.pAdaptFsm.pFsm
407 }
408 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
409 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
410 "device-id": oFsm.deviceID, "image-version": aImageVersion})
411 oFsm.useAPIVersion43 = true
412 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
413 oFsm.imageVersion = aImageVersion
414 oFsm.activateImage = true
415 oFsm.commitImage = aCommit
mpagenko9c225032021-10-15 14:26:49 +0000416 // indicate start of the upgrade activity
417 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000418 oFsm.mutexUpgradeParams.Unlock()
419 //directly request the FSM to activate the image
420 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
421 return nil
422 }
423 oFsm.mutexUpgradeParams.Unlock()
424 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
425 "device-id": oFsm.deviceID})
426 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
427}
428
429//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
430// called from 'new' API Commit_onu_image
mpagenko9c225032021-10-15 14:26:49 +0000431func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
432 aImageIdentifier string, aImageVersion string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000433 oFsm.mutexUpgradeParams.Lock()
434 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
435 // (as long as the Imageidentifier is correct)
436 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
mpagenko9c225032021-10-15 14:26:49 +0000437 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "image-version": aImageVersion})
438 if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000439 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
mpagenko9c225032021-10-15 14:26:49 +0000440 "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
441 "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
mpagenkoc26d4c02021-05-06 14:27:57 +0000442 oFsm.mutexUpgradeParams.Unlock()
443 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
444 oFsm.deviceID))
445 }
446 oFsm.commitImage = true
447 oFsm.mutexUpgradeParams.Unlock()
448 var pBaseFsm *fsm.FSM = nil
449 if oFsm.pAdaptFsm != nil {
450 pBaseFsm = oFsm.pAdaptFsm.pFsm
451 }
452 if pBaseFsm != nil {
mpagenko183647c2021-06-08 15:25:04 +0000453 //let the FSM decide if it is ready to process the event
454 logger.Debugw(ctx, "OnuUpgradeFsm requesting commit",
455 log.Fields{"device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
456 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000457 return nil
458 }
mpagenko9c225032021-10-15 14:26:49 +0000459 //should never occur
mpagenkoc26d4c02021-05-06 14:27:57 +0000460 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
461 "device-id": oFsm.deviceID})
462 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
463}
464
465//SetCommitmentParamsStart starts upgrade processing with immediate commitment
466// called from 'new' API Commit_onu_image
467func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
468 oFsm.mutexUpgradeParams.Lock()
469 var pBaseFsm *fsm.FSM = nil
470 if oFsm.pAdaptFsm != nil {
471 pBaseFsm = oFsm.pAdaptFsm.pFsm
472 }
473 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
474 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
475 "device-id": oFsm.deviceID, "image-version": aImageVersion})
476 oFsm.useAPIVersion43 = true
477 oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
478 oFsm.imageVersion = aImageVersion
479 oFsm.commitImage = true
mpagenko9c225032021-10-15 14:26:49 +0000480 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000481 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000482 //directly request the FSM to commit the image
mpagenkoc26d4c02021-05-06 14:27:57 +0000483 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
484 return nil
485 }
486 oFsm.mutexUpgradeParams.Unlock()
487 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
488 "device-id": oFsm.deviceID})
489 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
490}
491
mpagenko1f8e8822021-06-25 14:10:21 +0000492//GetCommitFlag delivers the commit flag that was configured here
493func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
494 oFsm.mutexUpgradeParams.RLock()
495 defer oFsm.mutexUpgradeParams.RUnlock()
496 return oFsm.commitImage
497}
498
mpagenko9c225032021-10-15 14:26:49 +0000499//GetImageStates delivers the download/image states as per device protobuf or error indication
mpagenkoaa3afe92021-05-21 16:20:58 +0000500func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
mpagenko9c225032021-10-15 14:26:49 +0000501 aImageIdentifier string, aVersion string) *voltha.ImageState {
mpagenkoaa3afe92021-05-21 16:20:58 +0000502 pImageState := &voltha.ImageState{}
mpagenko9c225032021-10-15 14:26:49 +0000503 pImageState.Version = aVersion //version as requested
mpagenkoaa3afe92021-05-21 16:20:58 +0000504 // check if the request refers to some active image/version of the processing
505 oFsm.mutexUpgradeParams.RLock()
506 if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
507 pImageState.DownloadState = oFsm.volthaDownloadState
508 pImageState.Reason = oFsm.volthaDownloadReason
509 pImageState.ImageState = oFsm.volthaImageState
510 } else {
511 pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
512 pImageState.Reason = voltha.ImageState_NO_ERROR
513 pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
514 }
515 oFsm.mutexUpgradeParams.RUnlock()
mpagenko9c225032021-10-15 14:26:49 +0000516 return pImageState
mpagenkoaa3afe92021-05-21 16:20:58 +0000517}
518
mpagenko9c225032021-10-15 14:26:49 +0000519//SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
520func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
mpagenko183647c2021-06-08 15:25:04 +0000521 oFsm.mutexUpgradeParams.Lock()
522 defer oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000523 oFsm.upgradePhase = cUpgradeActivated
524 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
mpagenko183647c2021-06-08 15:25:04 +0000525}
526
mpagenkoc26d4c02021-05-06 14:27:57 +0000527//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko9c225032021-10-15 14:26:49 +0000528func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
529 aReason voltha.ImageState_ImageFailureReason) {
530 pAdaptFsm := oFsm.pAdaptFsm
531 if pAdaptFsm == nil || pAdaptFsm.pFsm == nil {
532 logger.Warnw(ctx, "OnuUpgradeFsm cancel, but FSM invalid", log.Fields{
533 "device-id": oFsm.deviceID})
534 return
535 }
536 logger.Debugw(ctx, "OnuUpgradeFsm start canceling", log.Fields{
537 "device-id": oFsm.deviceID, "in fsm-state": pAdaptFsm.pFsm.Current()})
538 oFsm.mutexAbortRequest.Lock()
539 oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
540 oFsm.mutexAbortRequest.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000541 //mutex protection is required for possible concurrent access to FSM members
542 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
543 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
544 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
545 if oFsm.isWaitingForAdapterDlResponse {
546 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
547 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
548 oFsm.chAdapterDlReady <- false
549 } else {
550 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
551 }
Holger Hildebrandta4308972022-01-21 10:55:49 +0000552 //abort a possible delaying of sending EndSwDl
553 //use asynchronous channel sending to avoid blocking here in case no receiver is waiting
554 select {
555 case oFsm.chAbortDelayEndSwDl <- struct{}{}:
556 default:
557 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000558 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
559
560 // 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 +0000561 // specific here: See definition of state changes: some states are excluded from reset for possible later commit
mpagenko9c225032021-10-15 14:26:49 +0000562 pAdaptFsm = oFsm.pAdaptFsm
563 if pAdaptFsm != nil && pAdaptFsm.pFsm != nil {
mpagenkoc26d4c02021-05-06 14:27:57 +0000564 // calling FSM events in background to avoid blocking of the caller
mpagenko9c225032021-10-15 14:26:49 +0000565 go func(apFsm *fsm.FSM) {
566 if apFsm.Is(upgradeStWaitEndDL) {
567 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
568 } else if apFsm.Is(upgradeStAbortingDL) {
569 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //abort waiting on EndDownloadResponse
570 }
571
572 var err error
573 if abCompleteAbort {
574 // in case of unconditional abort request the ImageState is set immediately
575 oFsm.mutexUpgradeParams.Lock()
576 //any previous lingering conditional cancelRequest is superseded by this abortion
577 oFsm.conditionalCancelRequested = false
578 oFsm.volthaDownloadReason = aReason
579 oFsm.mutexUpgradeParams.Unlock()
580 err = apFsm.Event(upgradeEvAbort) //as unconditional default FSM cancellation
581 } else {
582 //at conditional abort request the image states are set when reaching the reset state
583 oFsm.mutexUpgradeParams.Lock()
584 oFsm.conditionalCancelRequested = true
585 oFsm.mutexUpgradeParams.Unlock()
586 err = apFsm.Event(upgradeEvReset) //as state-conditional default FSM cleanup
587 }
588 if err != nil {
589 //error return is expected in case of conditional request and no state transition
590 logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
591 "device-id": oFsm.deviceID, "error": err})
592 }
593 logger.Debugw(ctx, "OnuUpgradeFsm canceling done", log.Fields{
594 "device-id": oFsm.deviceID})
595 }(pAdaptFsm.pFsm)
596 } else { //the FSM seems already to be in some released state
597 logger.Warnw(ctx, "OnuUpgradeFsm canceling without FSM event", log.Fields{
598 "device-id": oFsm.deviceID, "in fsm-state": pAdaptFsm.pFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000599 }
600}
601
mpagenko80622a52021-02-09 16:53:23 +0000602func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
603 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
604 "device-id": oFsm.deviceID})
605
606 // start go routine for processing of LockState messages
607 go oFsm.processOmciUpgradeMessages(ctx)
608}
609
mpagenkoc26d4c02021-05-06 14:27:57 +0000610//enterWaitingAdapterDL state can only be reached with useAPIVersion43
611func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
612 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
613 "device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +0000614 syncChannel := make(chan struct{})
615 go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
616 //block until the wait routine is really blocked on chAdapterDlReady
617 <-syncChannel
mpagenkoc26d4c02021-05-06 14:27:57 +0000618 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
619}
620
mpagenko80622a52021-02-09 16:53:23 +0000621func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
622 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
623 "device-id": oFsm.deviceID})
624
mpagenkoc26d4c02021-05-06 14:27:57 +0000625 var fileLen int64
626 var err error
mpagenkoaa3afe92021-05-21 16:20:58 +0000627 oFsm.mutexUpgradeParams.Lock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000628 if oFsm.useAPIVersion43 {
629 //with the new API structure download to adapter is implicit and we have to wait until the image is available
630 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
631 } else {
632 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
633 }
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000634 if err != nil || fileLen == 0 || fileLen > int64(cMaxUint32) {
mpagenko9c225032021-10-15 14:26:49 +0000635 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000636 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000637 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
638 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
639 pBaseFsm := oFsm.pAdaptFsm
640 // Can't call FSM Event directly, decoupling it
641 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000642 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000643 }(pBaseFsm)
644 return
645 }
646
mpagenkoc26d4c02021-05-06 14:27:57 +0000647 //copy file content to buffer
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000648 var imageBuffer []byte
mpagenkoc26d4c02021-05-06 14:27:57 +0000649 if oFsm.useAPIVersion43 {
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000650 imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +0000651 } else {
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000652 imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
mpagenkoc26d4c02021-05-06 14:27:57 +0000653 }
mpagenko80622a52021-02-09 16:53:23 +0000654 if err != nil {
mpagenko9c225032021-10-15 14:26:49 +0000655 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000656 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000657 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
658 "device-id": oFsm.deviceID, "error": err})
659 pBaseFsm := oFsm.pAdaptFsm
660 // Can't call FSM Event directly, decoupling it
661 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000662 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000663 }(pBaseFsm)
664 return
665 }
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000666 //provide slice capacity already with the reserve of one section to avoid inflation of the slice to double size at append
667 oFsm.imageBuffer = make([]byte, fileLen, fileLen+cOmciDownloadSectionSize)
668 //better use a copy of the read image buffer in case the buffer/file is modified from outside,
669 // this also limits the slice len to the expected maximum fileLen
670 copy(oFsm.imageBuffer, imageBuffer)
mpagenko80622a52021-02-09 16:53:23 +0000671
672 oFsm.noOfSections = uint32(fileLen / cOmciDownloadSectionSize)
673 if fileLen%cOmciDownloadSectionSize > 0 {
mpagenkoc26d4c02021-05-06 14:27:57 +0000674 bufferPadding := make([]byte, cOmciDownloadSectionSize-uint32((fileLen)%cOmciDownloadSectionSize))
mpagenko80622a52021-02-09 16:53:23 +0000675 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000676 oFsm.imageBuffer = append(oFsm.imageBuffer, bufferPadding...)
mpagenko80622a52021-02-09 16:53:23 +0000677 oFsm.noOfSections++
678 }
679 oFsm.origImageLength = uint32(fileLen)
680 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000681 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
682 "MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
683 "ImageSize": oFsm.imageLength, "original file size": fileLen})
684 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
mpagenkoaa3afe92021-05-21 16:20:58 +0000685
686 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000687
688 // flush commMetricsChan
689 select {
690 case <-oFsm.chOnuDlReady:
691 logger.Debug(ctx, "flushed OnuDlReady channel")
692 default:
693 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000694 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
695
mpagenko9c225032021-10-15 14:26:49 +0000696 err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000697 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
698 if err != nil {
699 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
700 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000701 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000702 return
703 }
mpagenko9c225032021-10-15 14:26:49 +0000704 oFsm.isEndSwDlOpen = true
mpagenko80622a52021-02-09 16:53:23 +0000705}
706
707func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
708 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
709 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
mpagenko9c225032021-10-15 14:26:49 +0000710 //use a background routine to send the multiple download sections frames in a loop
Holger Hildebrandta4308972022-01-21 10:55:49 +0000711 // in order to avoid blocking on synchronous event calls for the entire (long) processing time
mpagenko9c225032021-10-15 14:26:49 +0000712 go oFsm.runSwDlSectionWindow(ctx)
713}
mpagenko80622a52021-02-09 16:53:23 +0000714
mpagenko9c225032021-10-15 14:26:49 +0000715//runSwDlSectionWindow runs a loop to send all DlSection frames of one window in background
716// may be aborted by parallel change of abortRequested
717func (oFsm *OnuUpgradeFsm) runSwDlSectionWindow(ctx context.Context) {
mpagenko80622a52021-02-09 16:53:23 +0000718 var windowAckRequest uint8 = 0
719 var bufferStartOffset uint32
720 var bufferEndOffset uint32
721 var downloadSection []byte
722 framePrint := false //default no printing of downloadSection frames
mpagenkoaa3afe92021-05-21 16:20:58 +0000723 oFsm.mutexUpgradeParams.Lock()
mpagenko9c225032021-10-15 14:26:49 +0000724 oFsm.upgradePhase = cUpgradeDownloading //start of downloading image to ONU
mpagenko80622a52021-02-09 16:53:23 +0000725 if oFsm.nextDownloadSectionsAbsolute == 0 {
726 //debug print of first section frame
727 framePrint = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000728 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
mpagenko80622a52021-02-09 16:53:23 +0000729 }
mpagenko80622a52021-02-09 16:53:23 +0000730 for {
mpagenko9c225032021-10-15 14:26:49 +0000731 oFsm.mutexAbortRequest.RLock()
732 // this way out of the section download loop on abort request
733 if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
734 //states are updated when entering the reset state ...
735 oFsm.volthaDownloadReason = oFsm.abortRequested
736 oFsm.mutexAbortRequest.RUnlock()
737 oFsm.mutexUpgradeParams.Unlock()
738 pUpgradeFsm := oFsm.pAdaptFsm
739 if pUpgradeFsm != nil {
740 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
741 logger.Debugw(ctx, "aborting runSwDlSectionWindow", log.Fields{
742 "device-id": oFsm.deviceID, "reason": oFsm.volthaDownloadReason})
743 return
744 }
745 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
746 return
747 }
748 oFsm.mutexAbortRequest.RUnlock()
749
mpagenko80622a52021-02-09 16:53:23 +0000750 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
751 bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
752 logger.Debugw(ctx, "DlSection values are", log.Fields{
753 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
754 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
755 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
756 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
757 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
758 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
759 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
mpagenko9c225032021-10-15 14:26:49 +0000760 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000761 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000762 //logical error -- reset the FSM
mpagenko9c225032021-10-15 14:26:49 +0000763 pUpgradeFsm := oFsm.pAdaptFsm
764 if pUpgradeFsm != nil {
765 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
766 return
767 }
768 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000769 return
770 }
771 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
772 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
773 windowAckRequest = 1
774 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
775 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
776 }
777 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
778 windowAckRequest = 1
779 framePrint = true //debug print of last frame
mpagenko15ff4a52021-03-02 10:09:20 +0000780 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
781 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000782 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
783 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000784 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko9c225032021-10-15 14:26:49 +0000785 err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000786 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
787 if err != nil {
788 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000789 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000790 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +0000791 return
792 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000793 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000794 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
795 if windowAckRequest == 1 {
mpagenkoaa3afe92021-05-21 16:20:58 +0000796 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000797 pUpgradeFsm := oFsm.pAdaptFsm
798 if pUpgradeFsm != nil {
799 _ = pUpgradeFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
800 return
801 }
802 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000803 return
804 }
805 framePrint = false //for the next Section frame (if wanted, can be enabled in logic before sendXXX())
806 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000807 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000808 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenkoaa3afe92021-05-21 16:20:58 +0000809 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko59498c12021-03-18 14:15:15 +0000810 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenkoaa3afe92021-05-21 16:20:58 +0000811 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000812 }
813 }
mpagenko9c225032021-10-15 14:26:49 +0000814} //runSwDlSectionWindow
mpagenko80622a52021-02-09 16:53:23 +0000815
816func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
817 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
818 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
819}
820
821func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000822 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000823 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
Holger Hildebrandta4308972022-01-21 10:55:49 +0000824 //use a background routine to wait EndSwDlDelay and then send the EndSwDl request
825 // in order to avoid blocking on synchronous event calls for the complete wait time
826 // and to allow for state transition before sending the EndSwDl request
827 go oFsm.delayAndSendEndSwDl(ctx)
828}
mpagenko80622a52021-02-09 16:53:23 +0000829
Holger Hildebrandta4308972022-01-21 10:55:49 +0000830//delayAndSendEndSwDl ensures a delay before sending the EndSwDl request
831// may also be aborted by parallel channel reception on chAbortEndSwDl
832func (oFsm *OnuUpgradeFsm) delayAndSendEndSwDl(ctx context.Context) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000833 oFsm.mutexUpgradeParams.RLock()
mpagenko80622a52021-02-09 16:53:23 +0000834 if oFsm.delayEndSwDl {
mpagenkoaa3afe92021-05-21 16:20:58 +0000835 oFsm.mutexUpgradeParams.RUnlock()
Holger Hildebrandta4308972022-01-21 10:55:49 +0000836 //give the ONU some time for image evaluation (hoping it does not only start this evaluation on first EndSwDl itself)
837 logger.Debugw(ctx, "OnuUpgradeFsm delay EndSwDl", log.Fields{"device-id": oFsm.deviceID,
838 "duration_s": cOmciEndSwDlDelaySeconds})
839 select {
840 case <-time.After(cOmciEndSwDlDelaySeconds * time.Second):
841 logger.Warnw(ctx, "OnuUpgradeFsm start sending EndSwDl", log.Fields{
842 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier})
843 case <-oFsm.chAbortDelayEndSwDl:
844 logger.Debugw(ctx, "OnuUpgradeFsm abort request to send EndSwDl", log.Fields{"device-id": oFsm.deviceID})
845 //according further state transition is ensured by the entity that sent the abort
846 return
847 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000848 } else {
849 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000850 }
mpagenko59498c12021-03-18 14:15:15 +0000851 pBaseFsm := oFsm.pAdaptFsm
852 if pBaseFsm == nil {
mpagenko9c225032021-10-15 14:26:49 +0000853 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
854 oFsm.mutexUpgradeParams.Lock()
855 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
856 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000857 // Can't call FSM Event directly, decoupling it
Holger Hildebrandta4308972022-01-21 10:55:49 +0000858 _ = pBaseFsm.pFsm.Event(upgradeEvAbort)
mpagenko59498c12021-03-18 14:15:15 +0000859 return
860 }
Holger Hildebrandta4308972022-01-21 10:55:49 +0000861 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx),
862 oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
863 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, 0, 0xFFFFFFFF)
mpagenko80622a52021-02-09 16:53:23 +0000864 if err != nil {
mpagenko9c225032021-10-15 14:26:49 +0000865 logger.Errorw(ctx, "EndSwDl abort: error sending EndSwDl", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000866 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000867 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000868 return
869 }
Holger Hildebrandta4308972022-01-21 10:55:49 +0000870 //from here on sending of EndSwDl(Abort) is not needed anymore (even though response is not yet received)
871 // this avoids sending of both EndSwDl(Success) and EndSwDl(Abort) when cancellation falls just into this window
872 // the ONU must theoretically be prepared to receive none of them (in case of OMCI transfer issues) e.g. by timeout
873 oFsm.isEndSwDlOpen = false
874 // wait for the EndSwDLResponse and check, if the ONU is ready for activation
875 _ = pBaseFsm.pFsm.Event(upgradeEvWaitEndDownload)
876} //delayAndSendEndSwDl
mpagenko59498c12021-03-18 14:15:15 +0000877
878func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
879 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
880 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
881 if oFsm.waitCountEndSwDl == 0 {
882 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
883 "device-id": oFsm.deviceID})
884 pBaseFsm := oFsm.pAdaptFsm
885 if pBaseFsm == nil {
886 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
887 "device-id": oFsm.deviceID})
888 return
889 }
mpagenko9c225032021-10-15 14:26:49 +0000890 oFsm.mutexUpgradeParams.Lock()
mpagenko9c225032021-10-15 14:26:49 +0000891 oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
892 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000893 go func(a_pAFsm *AdapterFsm) {
894 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
895 }(pBaseFsm)
896 return
897 }
898
899 oFsm.waitCountEndSwDl--
900 select {
901 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
902 pBaseFsm := oFsm.pAdaptFsm
903 if pBaseFsm == nil {
904 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
905 "device-id": oFsm.deviceID})
906 //FSM may be reset already from somewhere else, nothing we can do here anymore
907 return
908 }
909 //retry End SW DL
mpagenkoaa3afe92021-05-21 16:20:58 +0000910 oFsm.mutexUpgradeParams.Lock()
mpagenko59498c12021-03-18 14:15:15 +0000911 oFsm.delayEndSwDl = false //no more extra delay for the request
mpagenkoaa3afe92021-05-21 16:20:58 +0000912 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000913 go func(a_pAFsm *AdapterFsm) {
914 _ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
915 }(pBaseFsm)
916 return
917 case success := <-oFsm.chReceiveExpectedResponse:
918 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +0000919 oFsm.isEndSwDlOpen = false //no request to abort of download (already finished or immediate abort)
mpagenko59498c12021-03-18 14:15:15 +0000920 pBaseFsm := oFsm.pAdaptFsm
921 if pBaseFsm == nil {
922 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
923 "device-id": oFsm.deviceID})
924 //FSM may be reset already from somewhere else, nothing we can do here anymore
925 return
926 }
927 if success {
928 //answer received with ready indication
mpagenko9c225032021-10-15 14:26:49 +0000929 //useAPIVersion43 may not conflict in concurrency in this state function
930 if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
mpagenkoc26d4c02021-05-06 14:27:57 +0000931 go func(a_pAFsm *AdapterFsm) {
mpagenko9c225032021-10-15 14:26:49 +0000932 _ = a_pAFsm.pFsm.Event(upgradeEvCheckImageName)
mpagenkoc26d4c02021-05-06 14:27:57 +0000933 }(pBaseFsm)
mpagenko9c225032021-10-15 14:26:49 +0000934 } else { // elder API usage does not support image version check -immediately consider download as successful
935 if oFsm.activateImage {
936 //immediate activation requested
937 go func(a_pAFsm *AdapterFsm) {
938 _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
939 }(pBaseFsm)
940 } else {
941 //have to wait on explicit activation request
942 go func(a_pAFsm *AdapterFsm) {
943 _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
944 }(pBaseFsm)
945 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000946 }
mpagenko59498c12021-03-18 14:15:15 +0000947 return
948 }
949 //timer was aborted
mpagenko9c225032021-10-15 14:26:49 +0000950 oFsm.abortOnOmciError(ctx, true)
mpagenko59498c12021-03-18 14:15:15 +0000951 return
952 }
mpagenko80622a52021-02-09 16:53:23 +0000953}
954
mpagenko9c225032021-10-15 14:26:49 +0000955func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
956 logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
957 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
958 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
959 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
960 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
961 false, oFsm.pAdaptFsm.commChan)
962 if err != nil {
963 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
964 log.Fields{"device-id": oFsm.deviceID, "Error": err})
965 oFsm.abortOnOmciError(ctx, true)
966 return
967 }
968 oFsm.pLastTxMeInstance = meInstance
969}
970
mpagenko80622a52021-02-09 16:53:23 +0000971func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
972 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
973 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
974
mpagenkoaa3afe92021-05-21 16:20:58 +0000975 oFsm.mutexUpgradeParams.Lock()
976 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
977 oFsm.mutexUpgradeParams.Unlock()
978
mpagenko9c225032021-10-15 14:26:49 +0000979 err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000980 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
981 if err != nil {
982 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
983 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000984 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000985 return
986 }
mpagenko9c225032021-10-15 14:26:49 +0000987 oFsm.mutexUpgradeParams.Lock()
988 oFsm.upgradePhase = cUpgradeActivating //start of image activation for ONU
989 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
990 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000991}
992
993func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko9c225032021-10-15 14:26:49 +0000994 logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
995 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
996 //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
997 // (which is a bit problematic as the ONU might already be in committed state,
998 // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
999 if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
mpagenkoaa3afe92021-05-21 16:20:58 +00001000 oFsm.mutexUpgradeParams.Lock()
mpagenko9c225032021-10-15 14:26:49 +00001001 if activeImageID == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001002 inactiveImageID := oFsm.inactiveImageMeID
mpagenko15ff4a52021-03-02 10:09:20 +00001003 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
mpagenkoaa3afe92021-05-21 16:20:58 +00001004 "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
1005 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
mpagenko9c225032021-10-15 14:26:49 +00001006 oFsm.upgradePhase = cUpgradeCommitting //start of image commitment for ONU
mpagenkoaa3afe92021-05-21 16:20:58 +00001007 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +00001008 err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenkoaa3afe92021-05-21 16:20:58 +00001009 oFsm.pAdaptFsm.commChan, inactiveImageID) //more efficient activeImageID with above check
mpagenko15ff4a52021-03-02 10:09:20 +00001010 if err != nil {
1011 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
1012 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +00001013 oFsm.abortOnOmciError(ctx, true)
mpagenko15ff4a52021-03-02 10:09:20 +00001014 return
1015 }
1016 return
1017 }
mpagenko9c225032021-10-15 14:26:49 +00001018 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001019 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
1020 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
mpagenko9c225032021-10-15 14:26:49 +00001021 } else {
1022 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
1023 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +00001024 }
mpagenko9c225032021-10-15 14:26:49 +00001025 oFsm.mutexUpgradeParams.Lock()
1026 oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
1027 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1028 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001029 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1030 pBaseFsm := oFsm.pAdaptFsm
1031 // Can't call FSM Event directly, decoupling it
1032 go func(a_pAFsm *AdapterFsm) {
1033 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
1034 }(pBaseFsm)
1035}
1036
1037func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
mpagenko9c225032021-10-15 14:26:49 +00001038 logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +00001039 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
mpagenko15ff4a52021-03-02 10:09:20 +00001040 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
mpagenko9c225032021-10-15 14:26:49 +00001041 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra0b235842021-03-09 13:06:46 -08001042 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
mpagenko15ff4a52021-03-02 10:09:20 +00001043 //accept also nil as (error) return value for writing to LastTx
1044 // - this avoids misinterpretation of new received OMCI messages
ozgecanetsiab36ed572021-04-01 10:38:48 +03001045 if err != nil {
1046 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
1047 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko9c225032021-10-15 14:26:49 +00001048 oFsm.abortOnOmciError(ctx, true)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001049 return
1050 }
mpagenko15ff4a52021-03-02 10:09:20 +00001051 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +00001052}
1053
1054func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1055 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
1056
mpagenko9c225032021-10-15 14:26:49 +00001057 oFsm.stateUpdateOnReset(ctx)
1058
1059 oFsm.mutexAbortRequest.Lock()
1060 //to be sure to abort a possibly still running runSwDlSectionWindow()
1061 // in case the reset was not received from cancel() and download not finished correctly
1062 oFsm.abortRequested = oFsm.volthaDownloadReason
1063 oFsm.mutexAbortRequest.Unlock()
1064
mpagenkoc26d4c02021-05-06 14:27:57 +00001065 // in case the download-to-ONU timer is still running - cancel it
mpagenko9c225032021-10-15 14:26:49 +00001066 //use non-blocking channel (to be independent from receiver state)
1067 select {
1068 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1069 case oFsm.chOnuDlReady <- false:
1070 default:
1071 }
1072 pConfigUpgradeStateAFsm := oFsm.pAdaptFsm
1073 if pConfigUpgradeStateAFsm != nil {
1074 var nextEvent string
1075 if oFsm.isEndSwDlOpen {
1076 if oFsm.repeatAbort {
1077 oFsm.delayEndSwDl = true //run next abort with delay
1078 } else { //initial request
1079 oFsm.delayEndSwDl = false //run next abort with no delay
1080 oFsm.waitCountEndSwDl = cWaitCountEndSwDl //init for possible repetitions
1081 }
1082 nextEvent = upgradeEvAbortSwDownload
1083 } else {
1084 nextEvent = upgradeEvRestart
1085 }
1086 // Can't call FSM Event directly, decoupling it
1087 go func(a_pAFsm *AdapterFsm) {
1088 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1089 _ = a_pAFsm.pFsm.Event(nextEvent)
1090 }
1091 }(pConfigUpgradeStateAFsm)
1092 }
1093}
1094
1095func (oFsm *OnuUpgradeFsm) enterAbortingDL(ctx context.Context, e *fsm.Event) {
1096 logger.Debugw(ctx, "OnuUpgradeFsm aborting download to ONU", log.Fields{"device-id": oFsm.deviceID})
1097
1098 oFsm.mutexUpgradeParams.RLock()
1099 if oFsm.delayEndSwDl {
1100 oFsm.mutexUpgradeParams.RUnlock()
1101 //give the ONU some time for image discard activities
1102 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoc26d4c02021-05-06 14:27:57 +00001103 } else {
mpagenko9c225032021-10-15 14:26:49 +00001104 oFsm.mutexUpgradeParams.RUnlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001105 }
1106
mpagenko9c225032021-10-15 14:26:49 +00001107 pBaseFsm := oFsm.pAdaptFsm
1108 if pBaseFsm == nil {
1109 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
1110 return
1111 }
1112 // abort the download operation by sending an end software download message with invalid CRC and image size
1113 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx),
1114 oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
1115 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, 0, 0xFFFFFFFF)
1116 if err != nil {
1117 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: can't send EndSwDl request", log.Fields{"device-id": oFsm.deviceID})
1118 // Can't call FSM Event directly, decoupling it
1119 go func(a_pAFsm *AdapterFsm) {
1120 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1121 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1122 }
1123 }(pBaseFsm)
1124 return
1125 }
1126
1127 //avoid waiting in the enterXXX function here,
1128 // otherwise synchronous event calls (like from RxMessage processing) may block and block complete Rx processing then
1129 go oFsm.waitOnAbortEndSwDlResponse(ctx)
1130}
1131
1132//abortingDlEvaluateResponse waits for a channel indication with decision to proceed the FSM processing
1133func (oFsm *OnuUpgradeFsm) abortingDlEvaluateResponse(ctx context.Context,
1134 pBaseFsm *AdapterFsm, aResponseResult tEndSwDlResponseResult) bool {
1135 switch aResponseResult {
1136 case cEndSwDlResponseBusy: // indication for device busy, needs repetition
1137 if oFsm.waitCountEndSwDl == 0 {
1138 logger.Errorw(ctx, "aborting download: max limit of EndSwDl reached", log.Fields{
1139 "device-id": oFsm.deviceID})
1140 go func(a_pAFsm *AdapterFsm) {
1141 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1142 _ = a_pAFsm.pFsm.Event(upgradeEvRestart) //give up and let FSM terminate
1143 }
1144 }(pBaseFsm)
1145 } else {
1146 logger.Debugw(ctx, "aborting download: re-trigger sending abort SwDl", log.Fields{
1147 "device-id": oFsm.deviceID, "counter": oFsm.waitCountEndSwDl})
1148 oFsm.waitCountEndSwDl--
1149 oFsm.repeatAbort = true //repeated request in next round
1150 go func(a_pAFsm *AdapterFsm) {
1151 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1152 _ = a_pAFsm.pFsm.Event(upgradeEvReset) //which then re-triggers sending AbortSwDL
1153 }
1154 }(pBaseFsm)
1155 }
1156 return true
1157 case cEndSwDlResponseSuccess: // indication for success response
1158 logger.Infow(ctx, "aborting download: success response, terminating FSM", log.Fields{
1159 "device-id": oFsm.deviceID})
1160 case cEndSwDlResponseAbort: // indication for request to abort waiting for response
1161 logger.Infow(ctx, "aborting download: request to abort waiting, terminating FSM", log.Fields{
1162 "device-id": oFsm.deviceID})
1163 default:
1164 logger.Errorw(ctx, "aborting download: unknown channel indication, terminating FSM", log.Fields{
1165 "device-id": oFsm.deviceID})
1166 } //switch
1167 return false
1168}
1169
1170func (oFsm *OnuUpgradeFsm) enterRestarting(ctx context.Context, e *fsm.Event) {
1171 logger.Debugw(ctx, "OnuUpgradeFsm restarting", log.Fields{"device-id": oFsm.deviceID})
1172 pConfigUpgradeStateAFsm := oFsm.pAdaptFsm
1173 if pConfigUpgradeStateAFsm != nil {
mpagenko80622a52021-02-09 16:53:23 +00001174 // abort running message processing
1175 fsmAbortMsg := Message{
1176 Type: TestMsg,
1177 Data: TestMessage{
1178 TestMessageVal: AbortMessageProcessing,
1179 },
1180 }
mpagenko9c225032021-10-15 14:26:49 +00001181 pConfigUpgradeStateAFsm.commChan <- fsmAbortMsg
mpagenko80622a52021-02-09 16:53:23 +00001182
1183 //try to restart the FSM to 'disabled'
1184 // Can't call FSM Event directly, decoupling it
1185 go func(a_pAFsm *AdapterFsm) {
1186 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko9c225032021-10-15 14:26:49 +00001187 _ = a_pAFsm.pFsm.Event(upgradeEvDisable)
mpagenko80622a52021-02-09 16:53:23 +00001188 }
mpagenko9c225032021-10-15 14:26:49 +00001189 }(pConfigUpgradeStateAFsm)
mpagenko80622a52021-02-09 16:53:23 +00001190 }
1191}
1192
1193func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1194 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001195 // 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 +00001196 if oFsm.pDeviceHandler != nil {
1197 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenko9c225032021-10-15 14:26:49 +00001198 pLastUpgradeImageState := &voltha.ImageState{
1199 Version: oFsm.imageVersion,
1200 DownloadState: oFsm.volthaDownloadState,
1201 Reason: oFsm.volthaDownloadReason,
1202 ImageState: oFsm.volthaImageState,
1203 }
1204 go oFsm.pDeviceHandler.RemoveOnuUpgradeFsm(ctx, pLastUpgradeImageState)
mpagenko80622a52021-02-09 16:53:23 +00001205 }
1206}
1207
1208func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
1209 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
1210loop:
1211 for {
1212 // case <-ctx.Done():
1213 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
1214 // break loop
1215 message, ok := <-oFsm.pAdaptFsm.commChan
1216 if !ok {
1217 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
1218 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko9c225032021-10-15 14:26:49 +00001219 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +00001220 break loop
1221 }
1222 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
1223
1224 switch message.Type {
1225 case TestMsg:
1226 msg, _ := message.Data.(TestMessage)
1227 if msg.TestMessageVal == AbortMessageProcessing {
1228 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
1229 break loop
1230 }
1231 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
1232 case OMCI:
1233 msg, _ := message.Data.(OmciMessage)
1234 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
1235 default:
1236 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
1237 "message.Type": message.Type})
1238 }
1239 }
1240 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
1241}
1242
mpagenko80622a52021-02-09 16:53:23 +00001243func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg OmciMessage) {
1244 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
1245 "msgType": msg.OmciMsg.MessageType})
1246
1247 switch msg.OmciMsg.MessageType {
1248 case omci.StartSoftwareDownloadResponseType:
1249 {
mpagenko9c225032021-10-15 14:26:49 +00001250 oFsm.handleRxStartSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001251 return
1252 } //StartSoftwareDownloadResponseType
1253 case omci.DownloadSectionResponseType:
1254 {
mpagenko9c225032021-10-15 14:26:49 +00001255 oFsm.handleRxSwSectionResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001256 return
mpagenko80622a52021-02-09 16:53:23 +00001257 } //DownloadSectionResponseType
1258 case omci.EndSoftwareDownloadResponseType:
1259 {
mpagenko9c225032021-10-15 14:26:49 +00001260 oFsm.handleRxEndSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001261 return
1262 } //EndSoftwareDownloadResponseType
1263 case omci.ActivateSoftwareResponseType:
1264 {
1265 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1266 if msgLayer == nil {
1267 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1268 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001269 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001270 return
1271 }
1272 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1273 if !msgOk {
1274 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1275 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001276 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001277 return
1278 }
1279 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1280 "device-id": oFsm.deviceID, "data-fields": msgObj})
1281 if msgObj.Result != me.Success {
1282 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1283 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko9c225032021-10-15 14:26:49 +00001284 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001285 return
1286 }
mpagenko183647c2021-06-08 15:25:04 +00001287 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001288 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko9c225032021-10-15 14:26:49 +00001289 // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
mpagenko183647c2021-06-08 15:25:04 +00001290 oFsm.mutexUpgradeParams.Unlock()
1291 logger.Infow(ctx, "Expected ActivateSwResponse received",
1292 log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
1293 if oFsm.commitImage {
1294 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
1295 } else {
1296 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvActivationDone) // let the FSM wait for external commit request
1297 }
mpagenko80622a52021-02-09 16:53:23 +00001298 return
1299 }
mpagenko183647c2021-06-08 15:25:04 +00001300 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001301 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1302 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko9c225032021-10-15 14:26:49 +00001303 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001304 return
1305 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001306 case omci.CommitSoftwareResponseType:
1307 {
1308 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1309 if msgLayer == nil {
1310 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1311 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001312 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001313 return
1314 }
1315 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1316 if !msgOk {
1317 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1318 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001319 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001320 return
1321 }
mpagenkobf67a092021-03-17 09:52:28 +00001322 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001323 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1324 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko9c225032021-10-15 14:26:49 +00001325 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001326 return
mpagenkobf67a092021-03-17 09:52:28 +00001327 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001328 oFsm.mutexUpgradeParams.RLock()
mpagenko15ff4a52021-03-02 10:09:20 +00001329 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001330 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001331 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1332 //verifying committed image
1333 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
1334 return
1335 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001336 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001337 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1338 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko9c225032021-10-15 14:26:49 +00001339 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001340 return
1341 } //CommitSoftwareResponseType
1342 case omci.GetResponseType:
1343 {
mpagenko9c225032021-10-15 14:26:49 +00001344 oFsm.handleRxSwGetResponse(ctx, msg)
mpagenko15ff4a52021-03-02 10:09:20 +00001345 return
1346 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001347 default:
1348 {
1349 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1350 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1351 return
1352 }
1353 }
1354}
1355
mpagenko9c225032021-10-15 14:26:49 +00001356func (oFsm *OnuUpgradeFsm) handleRxStartSwDownloadResponse(ctx context.Context, msg OmciMessage) {
1357 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
1358 if msgLayer == nil {
1359 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
1360 log.Fields{"device-id": oFsm.deviceID})
1361 oFsm.abortOnOmciError(ctx, false)
1362 return
1363 }
1364 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
1365 if !msgOk {
1366 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
1367 log.Fields{"device-id": oFsm.deviceID})
1368 oFsm.abortOnOmciError(ctx, false)
1369 return
1370 }
1371 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
1372 "device-id": oFsm.deviceID, "data-fields": msgObj})
1373 if msgObj.Result != me.Success {
1374 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
1375 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1376 oFsm.abortOnOmciError(ctx, false)
1377 return
1378 }
1379
1380 oFsm.mutexUpgradeParams.Lock()
1381 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1382 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1383 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
1384 // also response WindowSize = 0 is a valid number for used Window size 1
1385 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
1386 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
1387 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
1388 }
1389 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
1390 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
1391 oFsm.noOfWindows++
1392 }
1393 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
1394 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
1395 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
1396 oFsm.nextDownloadSectionsAbsolute = 0
1397 oFsm.nextDownloadSectionsWindow = 0
1398 oFsm.nextDownloadWindow = 0
1399
1400 oFsm.mutexUpgradeParams.Unlock()
1401 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
1402 return
1403 }
1404 oFsm.mutexUpgradeParams.Unlock()
1405 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1406 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1407 oFsm.abortOnOmciError(ctx, false)
1408} //handleRxStartSwDownloadResponse
1409
1410func (oFsm *OnuUpgradeFsm) handleRxSwSectionResponse(ctx context.Context, msg OmciMessage) {
1411 if oFsm.pAdaptFsm == nil {
1412 logger.Infow(ctx, "DlSectionResponse received - but FSM not really valid anymore", log.Fields{
1413 "device-id": oFsm.deviceID})
1414 return
1415 }
1416 if !oFsm.pAdaptFsm.pFsm.Is(upgradeStVerifyWindow) {
1417 //all the processing here is only relevant if the FSM is in state upgradeStVerifyWindow
1418 // otherwise this response can be ignored (may stem from a long-processing window send activity,
1419 // which is not anymore relevant based on intermediate (cancel) state transitions)
1420 logger.Infow(ctx, "DlSectionResponse received - but ignored", log.Fields{
1421 "device-id": oFsm.deviceID, "fsm-state": oFsm.pAdaptFsm.pFsm.Current()})
1422 return
1423 }
1424 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
1425 if msgLayer == nil {
1426 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
1427 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
1428 oFsm.abortOnOmciError(ctx, false)
1429 return
1430 }
1431 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
1432 if !msgOk {
1433 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
1434 log.Fields{"device-id": oFsm.deviceID})
1435 oFsm.abortOnOmciError(ctx, false)
1436 return
1437 }
1438 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
1439 "device-id": oFsm.deviceID, "data-fields": msgObj})
1440 if msgObj.Result != me.Success {
1441 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
1442 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1443 oFsm.abortOnOmciError(ctx, false)
1444 return
1445 }
1446 oFsm.mutexUpgradeParams.Lock()
1447 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1448 sectionNumber := msgObj.SectionNumber
1449 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
1450 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
1451
1452 oFsm.nextDownloadWindow++
1453 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
1454 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
1455 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
1456 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
1457 "expected section": oFsm.omciDownloadWindowSizeLast})
1458 oFsm.mutexUpgradeParams.Unlock()
1459 oFsm.abortOnOmciError(ctx, false)
1460 return
1461 }
1462 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
1463 //CRC computation for all data bytes of the file
1464 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
1465 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
1466 var byteSlice []byte = make([]byte, 4)
1467 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
1468 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
1469 oFsm.mutexUpgradeParams.Unlock()
1470 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
1471 return
1472 }
1473 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
1474 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
1475 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
1476 "expected section": oFsm.omciDownloadWindowSizeLimit})
1477 oFsm.mutexUpgradeParams.Unlock()
1478 oFsm.abortOnOmciError(ctx, false)
1479 return
1480 }
1481 oFsm.nextDownloadSectionsWindow = 0
1482 oFsm.mutexUpgradeParams.Unlock()
1483 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
1484 return
1485 }
1486 oFsm.mutexUpgradeParams.Unlock()
1487 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1488 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1489 oFsm.abortOnOmciError(ctx, false)
1490} //handleRxSwSectionResponse
1491
1492func (oFsm *OnuUpgradeFsm) handleRxEndSwDownloadResponse(ctx context.Context, msg OmciMessage) {
1493 inAbortingState := oFsm.pAdaptFsm.pFsm.Is(upgradeStAbortingDL)
1494
1495 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1496 if msgLayer == nil {
1497 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1498 log.Fields{"device-id": oFsm.deviceID})
1499 if !inAbortingState {
1500 oFsm.abortOnOmciError(ctx, false)
1501 } //else using error log and wait for another response or 'aborting' state timeout
1502 return
1503 }
1504 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1505 if !msgOk {
1506 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1507 log.Fields{"device-id": oFsm.deviceID})
1508 if !inAbortingState {
1509 oFsm.abortOnOmciError(ctx, false)
1510 } //else using error log and wait for another response or 'aborting' state timeout
1511 return
1512 }
1513 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1514 "device-id": oFsm.deviceID, "data-fields": msgObj})
1515 if msgObj.Result != me.Success {
1516 if msgObj.Result == me.DeviceBusy {
1517 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1518 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1519 "device-id": oFsm.deviceID})
1520 if inAbortingState {
1521 //if the EndSwDl was requested from state AbortingDL then use channel to indicate ONU busy/repeat indication
1522 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseBusy //repeat abort request
1523 }
mpagenko9c225032021-10-15 14:26:49 +00001524 return
1525 }
1526 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
1527 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1528 if inAbortingState {
1529 //if the EndSwDl was requested from state AbortingDL and response is error indication
1530 // that would be quite strange ONU behavior, no resolution from OnuAdapter, just let the FSM go on to disabled
1531 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //error indication to abort waiting on EndDownloadResponse
1532 } //else using error log and wait for another response or 'aborting' state timeout
1533 return
1534 }
1535 oFsm.mutexUpgradeParams.Lock()
1536 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1537 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001538 if inAbortingState {
1539 oFsm.mutexUpgradeParams.Unlock()
1540 //if the EndSwDl was requested from state AbortingDL then use channel to indicate abort acceptance
1541 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseSuccess //success
1542 return
1543 }
1544 if !oFsm.useAPIVersion43 {
1545 //in the older API version the image version check was not possible
1546 // - assume new loaded image as valid-inactive immediately
1547 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1548 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1549 oFsm.mutexUpgradeParams.Unlock()
1550 //use non-blocking channel (to be independent from receiver state)
1551 select {
1552 //use non-blocking channel to indicate that the download to ONU was successful
1553 case oFsm.chOnuDlReady <- true:
1554 default:
1555 }
1556 } else {
1557 oFsm.mutexUpgradeParams.Unlock()
1558 }
1559 //use asynchronous channel sending to let the FSM proceed
1560 select {
1561 case oFsm.chReceiveExpectedResponse <- true:
1562 default:
1563 }
1564 return
1565 }
1566 oFsm.mutexUpgradeParams.Unlock()
1567 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: ignoring",
1568 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1569 // no state abort in case of unexpected ImageId, just keep waiting for the correct one
1570} //handleRxEndSwDownloadResponse
1571
1572func (oFsm *OnuUpgradeFsm) handleRxSwGetResponse(ctx context.Context, msg OmciMessage) {
1573 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1574 if msgLayer == nil {
1575 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1576 log.Fields{"device-id": oFsm.deviceID})
1577 oFsm.abortOnOmciError(ctx, false)
1578 return
1579 }
1580 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1581 if !msgOk {
1582 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1583 log.Fields{"device-id": oFsm.deviceID})
1584 oFsm.abortOnOmciError(ctx, false)
1585 return
1586 }
1587 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1588 "device-id": oFsm.deviceID, "data-fields": msgObj})
1589 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1590 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1591 if msgObj.Result != me.Success {
1592 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1593 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1594 oFsm.abortOnOmciError(ctx, false)
1595 return
1596 }
1597 } else {
1598 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1599 log.Fields{"device-id": oFsm.deviceID})
1600 return
1601 }
1602
1603 meAttributes := msgObj.Attributes
1604 imageIsCommitted := meAttributes["IsCommitted"].(uint8)
1605 imageIsActive := meAttributes["IsActive"].(uint8)
1606 imageVersion := TrimStringFromMeOctet(meAttributes["Version"])
1607 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
1608 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1609 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
1610
1611 if oFsm.pAdaptFsm.pFsm.Current() == upgradeStCheckImageName {
1612 //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
1613 oFsm.verifyOnuSwStatusAfterDownload(ctx, msgObj.EntityInstance, imageVersion, imageIsActive, imageIsCommitted)
1614 return
1615 }
1616
1617 //assumed only relevant state here is upgradeStCheckCommitted
1618 oFsm.mutexUpgradeParams.Lock()
1619 oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
1620 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive {
1621 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1622 // indicated in the download image version string (version must be part of the image content itself)
1623 // so checking that might be quite unreliable
1624 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1625 // in all the API references, so it can and should be checked here now
1626 if oFsm.useAPIVersion43 {
1627 if imageVersion != oFsm.imageVersion {
1628 //new active version indicated on OMCI from ONU is not the expected version
1629 logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
1630 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1631 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1632 // TODO!!!: error treatment?
1633 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1634 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1635 oFsm.mutexUpgradeParams.Unlock()
1636 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1637 return
1638 }
1639 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1640 log.Fields{"device-id": oFsm.deviceID})
1641 }
1642 if imageIsCommitted == swIsCommitted {
1643 oFsm.upgradePhase = cUpgradeCommitted
1644 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
1645 //store the new commit flag to onuSwImageIndications (to keep them in sync)
1646 oFsm.pDevEntry.ModifySwImageActiveCommit(ctx, imageIsCommitted)
1647 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
1648 //deviceProcStatusUpdate not used anymore,
1649 // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
1650 oFsm.mutexUpgradeParams.Unlock()
1651 //releasing the upgrade FSM on success
1652 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1653 return
1654 }
1655 //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
1656 }
1657 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1658 oFsm.mutexUpgradeParams.Unlock()
1659 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1660 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1661 // TODO!!!: error treatment?
1662 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1663 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1664} //handleRxSwGetResponse
1665
1666func (oFsm *OnuUpgradeFsm) verifyOnuSwStatusAfterDownload(ctx context.Context, aInstanceID uint16,
1667 aImageVersion string, aImageIsActive uint8, aImageIsCommitted uint8) {
1668 oFsm.mutexUpgradeParams.Lock()
1669 if aInstanceID == oFsm.inactiveImageMeID && aImageIsActive == swIsInactive &&
1670 aImageIsCommitted == swIsUncommitted {
1671 if aImageVersion != oFsm.imageVersion {
1672 //new stored inactive version indicated on OMCI from ONU is not the expected version
1673 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
1674 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID,
1675 "onu-version": aImageVersion, "expected-version": oFsm.imageVersion})
1676 //download state is set when entering the reset state
1677 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1678 oFsm.mutexUpgradeParams.Unlock()
1679 //stop the running ONU download timer
1680 //use non-blocking channel (to be independent from receiver state)
1681 select {
1682 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1683 case oFsm.chOnuDlReady <- false:
1684 default:
1685 }
1686 // TODO!!!: error treatment?
1687 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1688 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1689 return
1690 }
1691 //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
1692 oFsm.upgradePhase = cUpgradeDownloaded
1693 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1694 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1695 //store the new inactive version to onuSwImageIndications (to keep them in sync)
1696 oFsm.pDevEntry.ModifySwImageInactiveVersion(ctx, oFsm.imageVersion)
1697 //proceed within upgrade FSM
1698 if oFsm.activateImage {
1699 //immediate activation requested
1700 oFsm.mutexUpgradeParams.Unlock()
1701 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
1702 log.Fields{"device-id": oFsm.deviceID})
1703 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRequestActivate)
1704 } else {
1705 //have to wait on explicit activation request
1706 oFsm.mutexUpgradeParams.Unlock()
1707 logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
1708 log.Fields{"device-id": oFsm.deviceID})
1709 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForActivate)
1710 }
1711 //use non-blocking channel (to be independent from receiver state)
1712 select {
1713 //use non-blocking channel to indicate that the download to ONU was successful
1714 case oFsm.chOnuDlReady <- true:
1715 default:
1716 }
1717 return
1718 }
1719 //not the expected image/image state
1720 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1721 oFsm.mutexUpgradeParams.Unlock()
1722 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1723 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID})
1724 // TODO!!!: error treatment?
1725 //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
1726 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1727} //verifyOnuSwStatusAfterDownload
1728
1729//abortOnOmciError aborts the upgrade processing with evAbort
1730// asynchronous/synchronous based on parameter aAsync
1731func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool) {
1732 oFsm.mutexUpgradeParams.Lock()
1733 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1734 oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
1735 oFsm.mutexUpgradeParams.Unlock()
1736 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1737 if oFsm.pAdaptFsm != nil {
1738 var err error
1739 if aAsync { //asynchronous call requested to ensure state transition
1740 go func(a_pAFsm *AdapterFsm) {
1741 if a_pAFsm.pFsm != nil {
1742 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1743 }
1744 }(oFsm.pAdaptFsm)
1745 } else {
1746 if oFsm.pAdaptFsm.pFsm != nil {
1747 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1748 }
1749 }
1750 if err != nil {
1751 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1752 "device-id": oFsm.deviceID, "error": err})
1753 }
1754 }
1755}
1756
mpagenkoc26d4c02021-05-06 14:27:57 +00001757//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
mpagenko9c225032021-10-15 14:26:49 +00001758// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
1759func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
1760 aWaitChannel chan bool) {
mpagenkoc26d4c02021-05-06 14:27:57 +00001761 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
mpagenko9c225032021-10-15 14:26:49 +00001762 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
mpagenkoc26d4c02021-05-06 14:27:57 +00001763 oFsm.isWaitingForAdapterDlResponse = true
1764 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko9c225032021-10-15 14:26:49 +00001765 aSyncChannel <- struct{}{}
mpagenko80622a52021-02-09 16:53:23 +00001766 select {
1767 // maybe be also some outside cancel (but no context modeled for the moment ...)
1768 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001769 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1770 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1771 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1772 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1773 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
mpagenko9c225032021-10-15 14:26:49 +00001774 //running into timeout here may still have the download to adapter active -> abort
1775 oFsm.pFileManager.CancelDownload(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +00001776 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1777 oFsm.isWaitingForAdapterDlResponse = false
1778 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko9c225032021-10-15 14:26:49 +00001779 oFsm.mutexUpgradeParams.Lock()
1780 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1781 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'DOWNLOAD_TO_ADAPTER_TIMEOUT' would be better (proto)
1782 oFsm.mutexUpgradeParams.Unlock()
1783 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1784 if oFsm.pAdaptFsm != nil && oFsm.pAdaptFsm.pFsm != nil {
1785 err := oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1786 if err != nil {
1787 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1788 "device-id": oFsm.deviceID, "error": err})
1789 }
mpagenko80622a52021-02-09 16:53:23 +00001790 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001791 return
1792
1793 case success := <-aWaitChannel:
1794 if success {
1795 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1796 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1797 oFsm.isWaitingForAdapterDlResponse = false
1798 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1799 //let the upgrade process proceed
1800 pUpgradeFsm := oFsm.pAdaptFsm
1801 if pUpgradeFsm != nil {
1802 _ = pUpgradeFsm.pFsm.Event(upgradeEvPrepareSwDownload)
1803 } else {
1804 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1805 }
1806 return
1807 }
mpagenko9c225032021-10-15 14:26:49 +00001808 // waiting was aborted (assumed here to be caused by
1809 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001810 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1811 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1812 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1813 oFsm.isWaitingForAdapterDlResponse = false
1814 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001815 return
mpagenko80622a52021-02-09 16:53:23 +00001816 }
1817}
mpagenkoc26d4c02021-05-06 14:27:57 +00001818
1819//waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1820func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1821 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1822 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1823 "duration": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001824 select {
1825 // maybe be also some outside cancel (but no context modeled for the moment ...)
1826 // case <-ctx.Done():
1827 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1828 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1829 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1830 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001831 //the upgrade process has to be aborted
mpagenko9c225032021-10-15 14:26:49 +00001832 oFsm.abortOnOmciError(ctx, false)
mpagenkoc26d4c02021-05-06 14:27:57 +00001833 return
1834
1835 case success := <-aWaitChannel:
1836 if success {
1837 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001838 //all fine, let the FSM proceed like defined from the sender of this event
1839 return
1840 }
1841 // waiting was aborted (assumed here to be caused by
mpagenko9c225032021-10-15 14:26:49 +00001842 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001843 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001844 return
1845 }
1846}
mpagenko9c225032021-10-15 14:26:49 +00001847
1848//waitOnAbortEndSwDlResponse waits for either abort/success or timeout of EndSwDownload (for abortion)
1849func (oFsm *OnuUpgradeFsm) waitOnAbortEndSwDlResponse(ctx context.Context) {
1850 logger.Debugw(ctx, "OnuUpgradeFsm start wait for EndSwDl response (abort)", log.Fields{"device-id": oFsm.deviceID})
1851 select {
1852 case <-time.After(oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second):
1853 logger.Warnw(ctx, "OnuUpgradeFsm aborting download: timeout - no response received", log.Fields{"device-id": oFsm.deviceID})
1854 pUpgradeFsm := oFsm.pAdaptFsm
1855 if pUpgradeFsm != nil {
1856 _ = pUpgradeFsm.pFsm.Event(upgradeEvRestart)
1857 } else {
1858 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1859 }
1860 return
1861 case response := <-oFsm.chReceiveAbortEndSwDlResponse:
1862 logger.Debugw(ctx, "OnuUpgradeFsm aborting download: response received",
1863 log.Fields{"device-id": oFsm.deviceID, "response": response})
1864 pUpgradeFsm := oFsm.pAdaptFsm
1865 if pUpgradeFsm != nil {
1866 if oFsm.abortingDlEvaluateResponse(ctx, pUpgradeFsm, response) {
1867 return //event sent from function already
1868 }
1869 _ = pUpgradeFsm.pFsm.Event(upgradeEvRestart)
1870 } else {
1871 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1872 }
1873 return
1874 } //select
1875}
1876
1877//stateUpdateOnReset writes the download and/or image state on entering the reset state according to FSM internal indications
1878func (oFsm *OnuUpgradeFsm) stateUpdateOnReset(ctx context.Context) {
1879 oFsm.mutexUpgradeParams.Lock()
1880 defer oFsm.mutexUpgradeParams.Unlock()
1881 if !oFsm.conditionalCancelRequested {
1882 switch oFsm.upgradePhase {
1883 case cUpgradeUndefined, cUpgradeDownloading: //coming from downloading
1884 //make sure the download state is only changed in case the device has still been downloading
1885 if oFsm.volthaDownloadReason == voltha.ImageState_CANCELLED_ON_REQUEST {
1886 // indication for termination on request
1887 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
1888 } else if oFsm.volthaDownloadReason != voltha.ImageState_NO_ERROR {
1889 // indication for termination on failure
1890 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1891 }
1892 //reset the image state from Downloading in this case
1893 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1894 //in all other upgrade phases the last set download state remains valid
1895 case cUpgradeActivating:
1896 //reset the image state from Activating in this case
1897 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATION_ABORTED
1898 case cUpgradeCommitting: // indication for request to abort waiting for response
1899 //reset the image state from Activating in this case
1900 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
1901 //default: in all other upgrade phases keep the last set imageState
1902 } //switch
1903 } else {
1904 //when reaching reset state with conditional cancel that can only result from ONU related problems
1905 // (mostly ONU down indication) - derived from resetFsms call
1906 // and it can only be related to the downloading-to-ONU phase (no need to check that additionally)
1907 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1908 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1909 //reset the image state from Downloading in this case
1910 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1911 }
1912}
Holger Hildebrandtddc4fbd2022-02-04 14:10:36 +00001913
1914// PrepareForGarbageCollection - remove references to prepare for garbage collection
1915func (oFsm *OnuUpgradeFsm) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
1916 logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})
1917 oFsm.pDeviceHandler = nil
1918 oFsm.pDownloadManager = nil
1919 oFsm.pFileManager = nil
1920 oFsm.pDevEntry = nil
1921 oFsm.pOmciCC = nil
1922}