blob: 3ef46120bb92a5cb28e3969f5f61b71eef104058 [file] [log] [blame]
mpagenko80622a52021-02-09 16:53:23 +00001/*
Joey Armstrong89c812c2024-01-12 19:00:20 -05002 * Copyright 2020-2024 Open Networking Foundation (ONF) and the ONF Contributors
mpagenko80622a52021-02-09 16:53:23 +00003 *
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
Joey Armstrong89c812c2024-01-12 19:00:20 -050017// Package swupg provides the utilities for onu sw upgrade
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000018package swupg
mpagenko80622a52021-02-09 16:53:23 +000019
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"
mpagenko836a1fd2021-11-01 16:12:42 +000030 "github.com/opencord/omci-lib-go/v2"
31 me "github.com/opencord/omci-lib-go/v2/generated"
khenaidoo7d3c5582021-08-11 18:09:44 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000033 cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
34 "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/devdb"
kesavand011d5162021-11-25 19:21:06 +053035 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo7d3c5582021-08-11 18:09:44 -040036 "github.com/opencord/voltha-protos/v5/go/voltha"
mpagenko80622a52021-02-09 16:53:23 +000037)
38
39const cMaxUint32 = ^uint32(0)
40
41const (
42 // internal predefined values - some off them should later be configurable (perhaps with theses as defaults)
Holger Hildebrandt5458d892022-05-31 09:52:06 +000043 cOmciDownloadSectionSizeBaseLine = 31 //in bytes
44 cOmciDownloadWindowSizeLimitBaseLine = 31 //in sections for window offset (windowSize(32)-1)
45 cOmciDownloadSectionSizeExtLine = 1965 //in bytes
46 cOmciDownloadWindowSizeLimitExtLine = 7 //in sections for window offset (windowSize(8)-1)
mpagenko80622a52021-02-09 16:53:23 +000047 //cOmciDownloadWindowRetryMax = 2 // max attempts for a specific window
mpagenkoc26d4c02021-05-06 14:27:57 +000048 cOmciSectionInterleaveMilliseconds = 0 //DownloadSection interleave time in milliseconds (0 for no delay)
49 cOmciEndSwDlDelaySeconds = 1 //End Software Download delay after last section (may be also configurable?)
50 cWaitCountEndSwDl = 6 //maximum number of EndSwDl requests
51 cWaitDelayEndSwDlSeconds = 10 //duration, how long is waited before next request on EndSwDl
mpagenko80622a52021-02-09 16:53:23 +000052 //cOmciDownloadCompleteTimeout = 5400 //in s for the complete timeout (may be better scale to image size/ noOfWindows)
mgouda2b946fd2025-06-16 17:54:21 +053053 cMaxRetryAttemptsForDownloadWindow = 3 //maximun number of retry attempts to download the window
mpagenko80622a52021-02-09 16:53:23 +000054)
55
mpagenko45586762021-10-01 08:30:22 +000056// tEndSwDlResponseResult - Response result from EndSwDownload as used in channel indication
57type tUpgradePhase uint8
58
59const (
60 // undefined phase
61 cUpgradeUndefined tUpgradePhase = iota
62 // downloading image
63 cUpgradeDownloading
64 // image downloaded
65 cUpgradeDownloaded
66 // activating image
67 cUpgradeActivating
68 // image activated
69 cUpgradeActivated
70 // committing image
71 cUpgradeCommitting
72 // image committed
73 cUpgradeCommitted
74)
75
76// tEndSwDlResponseResult - Response result from EndSwDownload as used in channel indication
77type tEndSwDlResponseResult uint8
78
79const (
80 // response success
81 cEndSwDlResponseSuccess tEndSwDlResponseResult = iota
82 // response busy (repeat)
83 cEndSwDlResponseBusy
84 // response error or abort waiting for response
85 cEndSwDlResponseAbort
86)
87
mgouda2b946fd2025-06-16 17:54:21 +053088const (
89 ResultErr = "result error"
90)
91
mpagenko45586762021-10-01 08:30:22 +000092// upgrade FSM related events
mpagenko80622a52021-02-09 16:53:23 +000093const (
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000094 UpgradeEvStart = "UpgradeEvStart"
95 UpgradeEvDisable = "UpgradeEvDisable"
96 UpgradeEvAdapterDownload = "UpgradeEvAdapterDownload"
97 UpgradeEvPrepareSwDownload = "UpgradeEvPrepareSwDownload"
98 UpgradeEvRxStartSwDownload = "UpgradeEvRxStartSwDownload"
99 UpgradeEvWaitWindowAck = "UpgradeEvWaitWindowAck"
100 UpgradeEvContinueNextWindow = "UpgradeEvContinueNextWindow"
101 UpgradeEvEndSwDownload = "UpgradeEvEndSwDownload"
102 UpgradeEvWaitEndDownload = "UpgradeEvWaitEndDownload"
103 UpgradeEvContinueFinalize = "UpgradeEvContinueFinalize"
104 UpgradeEvCheckImageName = "UpgradeEvCheckImageName"
105 UpgradeEvWaitForActivate = "UpgradeEvWaitForActivate"
106 UpgradeEvRequestActivate = "UpgradeEvRequestActivate"
107 UpgradeEvActivationDone = "UpgradeEvActivationDone"
108 UpgradeEvWaitForCommit = "UpgradeEvWaitForCommit"
109 UpgradeEvCommitSw = "UpgradeEvCommitSw"
110 UpgradeEvCheckCommitted = "UpgradeEvCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +0000111
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000112 //UpgradeEvTimeoutSimple = "UpgradeEvTimeoutSimple"
113 //UpgradeEvTimeoutMids = "UpgradeEvTimeoutMids"
114 UpgradeEvReset = "UpgradeEvReset"
115 UpgradeEvAbort = "UpgradeEvAbort"
116 UpgradeEvRestart = "UpgradeEvRestart"
117 UpgradeEvAbortSwDownload = "UpgradeEvAbortSwDownload"
mpagenko80622a52021-02-09 16:53:23 +0000118)
119
mpagenko45586762021-10-01 08:30:22 +0000120// upgrade FSM related states
mpagenko80622a52021-02-09 16:53:23 +0000121const (
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000122 UpgradeStDisabled = "UpgradeStDisabled"
123 UpgradeStStarting = "UpgradeStStarting"
124 UpgradeStWaitingAdapterDL = "UpgradeStWaitingAdapterDL"
125 UpgradeStPreparingDL = "UpgradeStPreparingDL"
126 UpgradeStDLSection = "UpgradeStDLSection"
127 UpgradeStVerifyWindow = "UpgradeStVerifyWindow"
128 UpgradeStFinalizeDL = "UpgradeStFinalizeDL"
129 UpgradeStWaitEndDL = "UpgradeStWaitEndDL"
130 UpgradeStCheckImageName = "UpgradeStCheckImageName"
131 UpgradeStWaitForActivate = "UpgradeStWaitForActivate"
132 UpgradeStRequestingActivate = "UpgradeStRequestingActivate"
133 UpgradeStActivated = "UpgradeStActivated"
134 UpgradeStWaitForCommit = "UpgradeStWaitForCommit"
135 UpgradeStCommitSw = "UpgradeStCommitSw"
136 UpgradeStCheckCommitted = "UpgradeStCheckCommitted"
137 UpgradeStResetting = "UpgradeStResetting"
138 UpgradeStRestarting = "UpgradeStRestarting"
139 UpgradeStAbortingDL = "UpgradeStAbortingDL"
mpagenko80622a52021-02-09 16:53:23 +0000140)
141
Joey Armstrong89c812c2024-01-12 19:00:20 -0500142// COnuUpgradeFsmIdleState - required definition for IdleState detection for activities on OMCI
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000143const COnuUpgradeFsmIdleState = UpgradeStWaitForCommit
mpagenko80622a52021-02-09 16:53:23 +0000144
Joey Armstrong89c812c2024-01-12 19:00:20 -0500145// OnuUpgradeFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
mpagenko80622a52021-02-09 16:53:23 +0000146type OnuUpgradeFsm struct {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000147 pDeviceHandler cmn.IdeviceHandler
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530148 pDevEntry cmn.IonuDeviceEntry
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000149 pDownloadManager *AdapterDownloadManager
150 pFileManager *FileDownloadManager //used from R2.8 with new API version
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000151 pOmciCC *cmn.OmciCC
152 pOnuDB *devdb.OnuDeviceDB
mpagenko80622a52021-02-09 16:53:23 +0000153 //omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
mgouda2b946fd2025-06-16 17:54:21 +0530154 PAdaptFsm *cmn.AdapterFsm
155 pImageDsc *voltha.ImageDownload
156 pLastTxMeInstance *me.ManagedEntity
157 chReceiveExpectedResponse chan bool
158 chAdapterDlReady chan bool
159 chAbortDelayEndSwDl chan struct{}
160 chOnuDlReady chan bool
161 chReceiveAbortEndSwDlResponse chan tEndSwDlResponseResult
162 deviceID string
163 imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
164 imageIdentifier string //name of the image as used in the adapter
165 currentErrState string
166 imageBuffer []byte
167 requestEvent cmn.OnuDeviceEvent
168 downloadToOnuTimeout4MB time.Duration //timeout for downloading the image to the ONU for a 4MB image slice
169 omciSectionInterleaveDelay time.Duration //DownloadSectionInterleave delay in milliseconds
170 waitDelayEndSwDl time.Duration //duration, how long is waited before next request on EndSwDl
171 omciDownloadSectionSize int64
172 mutexUpgradeParams sync.RWMutex //mutex to protect members for parallel function requests and omci response processing
173 mutexIsAwaitingAdapterDlResponse sync.RWMutex
174 mutexAbortRequest sync.RWMutex
175 origImageLength uint32 //as also limited by OMCI
176 imageCRC uint32 //as per OMCI - ITU I.363.5 crc
177 imageLength uint32 //including last bytes padding
178 noOfSections uint32 //uint32 range for sections should be sufficient for very long images
179 nextDownloadSectionsAbsolute uint32 //number of next section to download in overall image
180 noOfWindows uint32 //uint32 range for windows should be sufficient for very long images
181 nextDownloadWindow uint32 //number of next window to download
182 abortRequested voltha.ImageState_ImageFailureReason
183 volthaDownloadState voltha.ImageState_ImageDownloadState
184 volthaDownloadReason voltha.ImageState_ImageFailureReason
185 volthaImageState voltha.ImageState_ImageActivationState
186 InactiveImageMeID uint16 //ME-ID of the inactive image
187 omciDownloadWindowSizeLimit uint8 //windowSize-1 in sections
188 omciDownloadWindowSizeLast uint8 //number of sections in last window
189 nextDownloadSectionsWindow uint8 //number of next section to download within current window
190 maxRetryAttemptsForDownloadWindow uint8
191 delayEndSwDl bool //flag to provide a delay between last section and EndSwDl
192 repeatAbort bool //flag to indicate if OMCI EndSwDownload (abort) is to be repeated
193 waitCountEndSwDl uint8 //number, how often is waited for EndSwDl at maximum
194 useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
195 isWaitingForAdapterDlResponse bool
196 activateImage bool
197 commitImage bool
198 conditionalCancelRequested bool
199 upgradePhase tUpgradePhase
200 isEndSwDlOpen bool
201 isExtendedOmci bool
mpagenko80622a52021-02-09 16:53:23 +0000202}
203
Joey Armstrong89c812c2024-01-12 19:00:20 -0500204// NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
205//
206// of ONU UNI ports via OMCI
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000207func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler cmn.IdeviceHandler,
208 apDevEntry cmn.IonuDeviceEntry, apOnuDB *devdb.OnuDeviceDB,
209 aRequestEvent cmn.OnuDeviceEvent, aName string, aCommChannel chan cmn.Message) *OnuUpgradeFsm {
mpagenko80622a52021-02-09 16:53:23 +0000210 instFsm := &OnuUpgradeFsm{
mgouda2b946fd2025-06-16 17:54:21 +0530211 pDeviceHandler: apDeviceHandler,
212 deviceID: apDeviceHandler.GetDeviceID(),
213 pDevEntry: apDevEntry,
214 pOmciCC: apDevEntry.GetDevOmciCC(),
215 pOnuDB: apOnuDB,
216 requestEvent: aRequestEvent,
217 omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
218 downloadToOnuTimeout4MB: apDeviceHandler.GetDlToOnuTimeout4M(),
219 waitCountEndSwDl: cWaitCountEndSwDl,
220 waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
221 upgradePhase: cUpgradeUndefined,
222 volthaDownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
223 volthaDownloadReason: voltha.ImageState_NO_ERROR,
224 volthaImageState: voltha.ImageState_IMAGE_UNKNOWN,
225 abortRequested: voltha.ImageState_NO_ERROR,
226 maxRetryAttemptsForDownloadWindow: cMaxRetryAttemptsForDownloadWindow,
mpagenko80622a52021-02-09 16:53:23 +0000227 }
mpagenko59498c12021-03-18 14:15:15 +0000228 instFsm.chReceiveExpectedResponse = make(chan bool)
mpagenkoc26d4c02021-05-06 14:27:57 +0000229 instFsm.chAdapterDlReady = make(chan bool)
mpagenko609a69a2021-12-02 08:12:58 +0000230 instFsm.chAbortDelayEndSwDl = make(chan struct{})
mpagenkoc26d4c02021-05-06 14:27:57 +0000231 instFsm.chOnuDlReady = make(chan bool)
mpagenko45586762021-10-01 08:30:22 +0000232 instFsm.chReceiveAbortEndSwDlResponse = make(chan tEndSwDlResponseResult)
mpagenko80622a52021-02-09 16:53:23 +0000233
Holger Hildebrandt5458d892022-05-31 09:52:06 +0000234 instFsm.isExtendedOmci = instFsm.pDevEntry.GetPersIsExtOmciSupported()
235 if instFsm.isExtendedOmci {
236 instFsm.omciDownloadSectionSize = cOmciDownloadSectionSizeExtLine
237 instFsm.omciDownloadWindowSizeLimit = cOmciDownloadWindowSizeLimitExtLine
238 } else {
239 instFsm.omciDownloadSectionSize = cOmciDownloadSectionSizeBaseLine
240 instFsm.omciDownloadWindowSizeLimit = cOmciDownloadWindowSizeLimitBaseLine
241 }
242
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000243 instFsm.PAdaptFsm = cmn.NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
244 if instFsm.PAdaptFsm == nil {
mpagenko80622a52021-02-09 16:53:23 +0000245 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
246 "device-id": instFsm.deviceID})
247 return nil
248 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000249 instFsm.PAdaptFsm.PFsm = fsm.NewFSM(
250 UpgradeStDisabled,
mpagenko80622a52021-02-09 16:53:23 +0000251 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000252 {Name: UpgradeEvStart, Src: []string{UpgradeStDisabled}, Dst: UpgradeStStarting},
253 {Name: UpgradeEvAdapterDownload, Src: []string{UpgradeStStarting}, Dst: UpgradeStWaitingAdapterDL},
254 {Name: UpgradeEvPrepareSwDownload, Src: []string{UpgradeStStarting, UpgradeStWaitingAdapterDL}, Dst: UpgradeStPreparingDL},
255 {Name: UpgradeEvRxStartSwDownload, Src: []string{UpgradeStPreparingDL}, Dst: UpgradeStDLSection},
256 {Name: UpgradeEvWaitWindowAck, Src: []string{UpgradeStDLSection}, Dst: UpgradeStVerifyWindow},
257 {Name: UpgradeEvContinueNextWindow, Src: []string{UpgradeStVerifyWindow}, Dst: UpgradeStDLSection},
258 {Name: UpgradeEvEndSwDownload, Src: []string{UpgradeStVerifyWindow}, Dst: UpgradeStFinalizeDL},
259 {Name: UpgradeEvWaitEndDownload, Src: []string{UpgradeStFinalizeDL}, Dst: UpgradeStWaitEndDL},
260 {Name: UpgradeEvContinueFinalize, Src: []string{UpgradeStWaitEndDL}, Dst: UpgradeStFinalizeDL},
261 //UpgradeStCheckImageName only used with useAPIVersion43
262 {Name: UpgradeEvCheckImageName, Src: []string{UpgradeStWaitEndDL}, Dst: UpgradeStCheckImageName},
263 //UpgradeEvWaitForActivate state transitions depend on useAPIVersion43
264 {Name: UpgradeEvWaitForActivate, Src: []string{UpgradeStWaitEndDL, UpgradeStCheckImageName}, Dst: UpgradeStWaitForActivate},
265 //UpgradeEvRequestActivate state transitions depend on useAPIVersion43
266 {Name: UpgradeEvRequestActivate, Src: []string{UpgradeStStarting, UpgradeStWaitEndDL, UpgradeStCheckImageName,
267 UpgradeStWaitForActivate}, Dst: UpgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
268 {Name: UpgradeEvActivationDone, Src: []string{UpgradeStRequestingActivate}, Dst: UpgradeStActivated},
269 {Name: UpgradeEvWaitForCommit, Src: []string{UpgradeStRequestingActivate}, Dst: UpgradeStWaitForCommit},
270 {Name: UpgradeEvCommitSw, Src: []string{UpgradeStStarting, UpgradeStRequestingActivate, UpgradeStWaitForCommit,
271 UpgradeStActivated}, Dst: UpgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
272 {Name: UpgradeEvCheckCommitted, Src: []string{UpgradeStCommitSw}, Dst: UpgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000273
274 /*
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000275 {Name: UpgradeEvTimeoutSimple, Src: []string{
276 UpgradeStCreatingDot1PMapper, UpgradeStCreatingMBPCD, UpgradeStSettingTconts, UpgradeStSettingDot1PMapper}, Dst: UpgradeStStarting},
277 {Name: UpgradeEvTimeoutMids, Src: []string{
278 UpgradeStCreatingGemNCTPs, UpgradeStCreatingGemIWs, UpgradeStSettingPQs}, Dst: UpgradeStStarting},
mpagenko80622a52021-02-09 16:53:23 +0000279 */
280 // exceptional treatments
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000281 //on UpgradeEvReset: UpgradeStRequestingActivate, UpgradeStWaitForCommit and UpgradeStActivated are not reset
mpagenko1f8e8822021-06-25 14:10:21 +0000282 // (to let the FSM survive the expected OnuDown indication)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000283 {Name: UpgradeEvReset, Src: []string{UpgradeStStarting, UpgradeStWaitingAdapterDL, UpgradeStPreparingDL, UpgradeStDLSection,
284 UpgradeStVerifyWindow, UpgradeStDLSection, UpgradeStFinalizeDL, UpgradeStWaitEndDL, UpgradeStCheckImageName,
285 UpgradeStWaitForActivate,
mpagenko45586762021-10-01 08:30:22 +0000286 UpgradeStCommitSw, UpgradeStCheckCommitted, UpgradeStAbortingDL},
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000287 Dst: UpgradeStResetting},
288 {Name: UpgradeEvAbort, Src: []string{UpgradeStStarting, UpgradeStWaitingAdapterDL, UpgradeStPreparingDL, UpgradeStDLSection,
289 UpgradeStVerifyWindow, UpgradeStDLSection, UpgradeStFinalizeDL, UpgradeStWaitEndDL, UpgradeStCheckImageName,
290 UpgradeStWaitForActivate,
291 UpgradeStRequestingActivate, UpgradeStActivated, UpgradeStWaitForCommit,
292 UpgradeStCommitSw, UpgradeStCheckCommitted},
293 Dst: UpgradeStResetting},
294 {Name: UpgradeEvAbortSwDownload, Src: []string{UpgradeStResetting}, Dst: UpgradeStAbortingDL},
295 {Name: UpgradeEvRestart, Src: []string{UpgradeStResetting, UpgradeStAbortingDL}, Dst: UpgradeStRestarting},
296 {Name: UpgradeEvDisable, Src: []string{UpgradeStRestarting}, Dst: UpgradeStDisabled},
mpagenko80622a52021-02-09 16:53:23 +0000297 },
298 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000299 "enter_state": func(e *fsm.Event) { instFsm.PAdaptFsm.LogFsmStateChange(ctx, e) },
300 "enter_" + UpgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
301 "enter_" + UpgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
302 "enter_" + UpgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
303 "enter_" + UpgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
304 "enter_" + UpgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
305 "enter_" + UpgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
306 "enter_" + UpgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
307 "enter_" + UpgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
308 "enter_" + UpgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
309 "enter_" + UpgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
310 "enter_" + UpgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
311 "enter_" + UpgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
312 "enter_" + UpgradeStAbortingDL: func(e *fsm.Event) { instFsm.enterAbortingDL(ctx, e) },
313 "enter_" + UpgradeStRestarting: func(e *fsm.Event) { instFsm.enterRestarting(ctx, e) },
314 "enter_" + UpgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000315 },
316 )
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000317 if instFsm.PAdaptFsm.PFsm == nil {
mpagenko80622a52021-02-09 16:53:23 +0000318 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
319 "device-id": instFsm.deviceID})
320 return nil
321 }
322
323 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
324 return instFsm
325}
326
Joey Armstrong89c812c2024-01-12 19:00:20 -0500327// SetDownloadParams configures the needed parameters for a specific download to the ONU
328//
329// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000330func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000331 apImageDsc *voltha.ImageDownload, apDownloadManager *AdapterDownloadManager) error {
332 pBaseFsm := oFsm.PAdaptFsm.PFsm
333 if pBaseFsm != nil && pBaseFsm.Is(UpgradeStStarting) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000334 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000335 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
336 "device-id": oFsm.deviceID, "image-description": apImageDsc})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000337 oFsm.InactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000338 oFsm.pImageDsc = apImageDsc
339 oFsm.pDownloadManager = apDownloadManager
Holger Hildebrandtac1e0592021-06-03 15:16:49 +0000340 oFsm.activateImage = true
341 oFsm.commitImage = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000342 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000343
344 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000345 // let the upgrade FSM proceed to PreparingDL
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000346 _ = aPBaseFsm.Event(UpgradeEvPrepareSwDownload)
mpagenko80622a52021-02-09 16:53:23 +0000347 }(pBaseFsm)
348 return nil
349 }
350 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
351 "device-id": oFsm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530352 return fmt.Errorf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID)
mpagenko80622a52021-02-09 16:53:23 +0000353}
354
Joey Armstrong89c812c2024-01-12 19:00:20 -0500355// SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
356//
357// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
358// called from 'new' API Download_onu_image
mpagenkoc26d4c02021-05-06 14:27:57 +0000359func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000360 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *FileDownloadManager,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000361 aImageIdentifier string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000362 oFsm.mutexUpgradeParams.Lock()
363 var pBaseFsm *fsm.FSM = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000364 if oFsm.PAdaptFsm != nil {
365 pBaseFsm = oFsm.PAdaptFsm.PFsm
mpagenkoc26d4c02021-05-06 14:27:57 +0000366 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000367 if pBaseFsm != nil && pBaseFsm.Is(UpgradeStStarting) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000368 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
369 "device-id": oFsm.deviceID, "image-description": apImageRequest})
370 oFsm.useAPIVersion43 = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000371 oFsm.InactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenkoc26d4c02021-05-06 14:27:57 +0000372 oFsm.pFileManager = apDownloadManager
373 oFsm.imageIdentifier = aImageIdentifier
374 oFsm.imageVersion = apImageRequest.Image.Version
375 oFsm.activateImage = apImageRequest.ActivateOnSuccess
376 oFsm.commitImage = apImageRequest.CommitOnSuccess
mpagenko45586762021-10-01 08:30:22 +0000377 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //state change indication for download request
mpagenkoc26d4c02021-05-06 14:27:57 +0000378 oFsm.mutexUpgradeParams.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000379 _ = pBaseFsm.Event(UpgradeEvAdapterDownload) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000380 return nil
381 }
382 oFsm.mutexUpgradeParams.Unlock()
383 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
384 "device-id": oFsm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530385 return fmt.Errorf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID)
mpagenkoc26d4c02021-05-06 14:27:57 +0000386}
387
Joey Armstrong89c812c2024-01-12 19:00:20 -0500388// SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
389//
390// called from 'new' API Activate_onu_image
mpagenkoc26d4c02021-05-06 14:27:57 +0000391func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
392 aImageIdentifier string, aCommit bool) error {
mpagenko45586762021-10-01 08:30:22 +0000393 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
394 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
mpagenkoc26d4c02021-05-06 14:27:57 +0000395 oFsm.mutexUpgradeParams.Lock()
396 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
397 // (as long as the Imageidentifier is correct)
mpagenkoc26d4c02021-05-06 14:27:57 +0000398 if aImageIdentifier != oFsm.imageIdentifier {
399 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
400 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
401 oFsm.mutexUpgradeParams.Unlock()
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530402 return fmt.Errorf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
403 oFsm.deviceID)
mpagenkoc26d4c02021-05-06 14:27:57 +0000404 }
405 oFsm.activateImage = true
406 oFsm.commitImage = aCommit
mpagenko45586762021-10-01 08:30:22 +0000407 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000408 var pBaseFsm *fsm.FSM = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000409 if oFsm.PAdaptFsm != nil {
410 pBaseFsm = oFsm.PAdaptFsm.PFsm
mpagenkoc26d4c02021-05-06 14:27:57 +0000411 }
412 if pBaseFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000413 if pBaseFsm.Is(UpgradeStWaitForActivate) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000414 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000415 _ = pBaseFsm.Event(UpgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenko38662d02021-08-11 09:45:19 +0000416 } else {
mpagenko38662d02021-08-11 09:45:19 +0000417 logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
418 "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000419 }
420 return nil
421 }
422 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
423 "device-id": oFsm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530424 return fmt.Errorf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID)
mpagenkoc26d4c02021-05-06 14:27:57 +0000425}
426
Joey Armstrong89c812c2024-01-12 19:00:20 -0500427// SetActivationParamsStart starts upgrade processing with immediate activation
428//
429// called from 'new' API Activate_onu_image
mpagenkoc26d4c02021-05-06 14:27:57 +0000430func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
431 oFsm.mutexUpgradeParams.Lock()
432 var pBaseFsm *fsm.FSM = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000433 if oFsm.PAdaptFsm != nil {
434 pBaseFsm = oFsm.PAdaptFsm.PFsm
mpagenkoc26d4c02021-05-06 14:27:57 +0000435 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000436 if pBaseFsm != nil && pBaseFsm.Is(UpgradeStStarting) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000437 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
438 "device-id": oFsm.deviceID, "image-version": aImageVersion})
439 oFsm.useAPIVersion43 = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000440 oFsm.InactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenkoc26d4c02021-05-06 14:27:57 +0000441 oFsm.imageVersion = aImageVersion
442 oFsm.activateImage = true
443 oFsm.commitImage = aCommit
mpagenko38662d02021-08-11 09:45:19 +0000444 // indicate start of the upgrade activity
mpagenko45586762021-10-01 08:30:22 +0000445 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000446 oFsm.mutexUpgradeParams.Unlock()
447 //directly request the FSM to activate the image
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000448 _ = pBaseFsm.Event(UpgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000449 return nil
450 }
451 oFsm.mutexUpgradeParams.Unlock()
452 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
453 "device-id": oFsm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530454 return fmt.Errorf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID)
mpagenkoc26d4c02021-05-06 14:27:57 +0000455}
456
Joey Armstrong89c812c2024-01-12 19:00:20 -0500457// SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
458//
459// called from 'new' API Commit_onu_image
mpagenko38662d02021-08-11 09:45:19 +0000460func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
461 aImageIdentifier string, aImageVersion string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000462 oFsm.mutexUpgradeParams.Lock()
463 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
464 // (as long as the Imageidentifier is correct)
465 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
mpagenkoa2b288f2021-10-21 11:25:27 +0000466 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "image-version": aImageVersion})
mpagenko38662d02021-08-11 09:45:19 +0000467 if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000468 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
mpagenko38662d02021-08-11 09:45:19 +0000469 "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
470 "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
mpagenkoc26d4c02021-05-06 14:27:57 +0000471 oFsm.mutexUpgradeParams.Unlock()
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530472 return fmt.Errorf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
473 oFsm.deviceID)
mpagenkoc26d4c02021-05-06 14:27:57 +0000474 }
475 oFsm.commitImage = true
476 oFsm.mutexUpgradeParams.Unlock()
477 var pBaseFsm *fsm.FSM = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000478 if oFsm.PAdaptFsm != nil {
479 pBaseFsm = oFsm.PAdaptFsm.PFsm
mpagenkoc26d4c02021-05-06 14:27:57 +0000480 }
481 if pBaseFsm != nil {
mpagenko183647c2021-06-08 15:25:04 +0000482 //let the FSM decide if it is ready to process the event
483 logger.Debugw(ctx, "OnuUpgradeFsm requesting commit",
484 log.Fields{"device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000485 _ = pBaseFsm.Event(UpgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000486 return nil
487 }
mpagenko38662d02021-08-11 09:45:19 +0000488 //should never occur
mpagenkoc26d4c02021-05-06 14:27:57 +0000489 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
490 "device-id": oFsm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530491 return fmt.Errorf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID)
mpagenkoc26d4c02021-05-06 14:27:57 +0000492}
493
Joey Armstrong89c812c2024-01-12 19:00:20 -0500494// SetCommitmentParamsStart starts upgrade processing with immediate commitment
495//
496// called from 'new' API Commit_onu_image
mpagenkoc26d4c02021-05-06 14:27:57 +0000497func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
498 oFsm.mutexUpgradeParams.Lock()
499 var pBaseFsm *fsm.FSM = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000500 if oFsm.PAdaptFsm != nil {
501 pBaseFsm = oFsm.PAdaptFsm.PFsm
mpagenkoc26d4c02021-05-06 14:27:57 +0000502 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000503 if pBaseFsm != nil && pBaseFsm.Is(UpgradeStStarting) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000504 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
505 "device-id": oFsm.deviceID, "image-version": aImageVersion})
506 oFsm.useAPIVersion43 = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000507 oFsm.InactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
mpagenkoc26d4c02021-05-06 14:27:57 +0000508 oFsm.imageVersion = aImageVersion
509 oFsm.commitImage = true
mpagenko45586762021-10-01 08:30:22 +0000510 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000511 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +0000512 //directly request the FSM to commit the image
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000513 _ = pBaseFsm.Event(UpgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000514 return nil
515 }
516 oFsm.mutexUpgradeParams.Unlock()
517 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
518 "device-id": oFsm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530519 return fmt.Errorf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID)
mpagenkoc26d4c02021-05-06 14:27:57 +0000520}
521
Joey Armstrong89c812c2024-01-12 19:00:20 -0500522// GetCommitFlag delivers the commit flag that was configured here
mpagenko1f8e8822021-06-25 14:10:21 +0000523func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
524 oFsm.mutexUpgradeParams.RLock()
525 defer oFsm.mutexUpgradeParams.RUnlock()
526 return oFsm.commitImage
527}
528
Joey Armstrong89c812c2024-01-12 19:00:20 -0500529// GetImageStates delivers the download/image states as per device proto buf definition
mpagenkoaa3afe92021-05-21 16:20:58 +0000530func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
mpagenko38662d02021-08-11 09:45:19 +0000531 aImageIdentifier string, aVersion string) *voltha.ImageState {
mpagenkoaa3afe92021-05-21 16:20:58 +0000532 pImageState := &voltha.ImageState{}
mpagenko38662d02021-08-11 09:45:19 +0000533 pImageState.Version = aVersion //version as requested
mpagenkoaa3afe92021-05-21 16:20:58 +0000534 // check if the request refers to some active image/version of the processing
535 oFsm.mutexUpgradeParams.RLock()
536 if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
537 pImageState.DownloadState = oFsm.volthaDownloadState
538 pImageState.Reason = oFsm.volthaDownloadReason
539 pImageState.ImageState = oFsm.volthaImageState
540 } else {
541 pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
542 pImageState.Reason = voltha.ImageState_NO_ERROR
543 pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
544 }
545 oFsm.mutexUpgradeParams.RUnlock()
mpagenko38662d02021-08-11 09:45:19 +0000546 return pImageState
mpagenkoaa3afe92021-05-21 16:20:58 +0000547}
548
Joey Armstrong89c812c2024-01-12 19:00:20 -0500549// SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
mpagenko38662d02021-08-11 09:45:19 +0000550func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
mpagenko183647c2021-06-08 15:25:04 +0000551 oFsm.mutexUpgradeParams.Lock()
552 defer oFsm.mutexUpgradeParams.Unlock()
mpagenko45586762021-10-01 08:30:22 +0000553 oFsm.upgradePhase = cUpgradeActivated
mpagenko38662d02021-08-11 09:45:19 +0000554 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
mpagenko38662d02021-08-11 09:45:19 +0000555}
556
Joey Armstrong89c812c2024-01-12 19:00:20 -0500557// CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko38662d02021-08-11 09:45:19 +0000558func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
559 aReason voltha.ImageState_ImageFailureReason) {
mpagenkoa2b288f2021-10-21 11:25:27 +0000560 pAdaptFsm := oFsm.PAdaptFsm
Holger Hildebrandt12609a12022-03-25 13:23:25 +0000561 logger.Debugw(ctx, "CancelProcessing entered", log.Fields{"device-id": oFsm.deviceID})
mpagenkoa2b288f2021-10-21 11:25:27 +0000562 if pAdaptFsm == nil || pAdaptFsm.PFsm == nil {
563 logger.Warnw(ctx, "OnuUpgradeFsm cancel, but FSM invalid", log.Fields{
564 "device-id": oFsm.deviceID})
565 return
566 }
567 logger.Debugw(ctx, "OnuUpgradeFsm start canceling", log.Fields{
568 "device-id": oFsm.deviceID, "in fsm-state": pAdaptFsm.PFsm.Current()})
mpagenko38662d02021-08-11 09:45:19 +0000569 oFsm.mutexAbortRequest.Lock()
570 oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
571 oFsm.mutexAbortRequest.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000572 //mutex protection is required for possible concurrent access to FSM members
573 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
574 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
575 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
576 if oFsm.isWaitingForAdapterDlResponse {
577 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
578 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
579 oFsm.chAdapterDlReady <- false
580 } else {
581 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
582 }
mpagenko609a69a2021-12-02 08:12:58 +0000583
584 //abort a possible delaying of sending EndSwDl
585 //use asynchronous channel sending to avoid blocking here in case no receiver is waiting
586 select {
587 case oFsm.chAbortDelayEndSwDl <- struct{}{}:
588 default:
589 }
590
mpagenkoc26d4c02021-05-06 14:27:57 +0000591 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
592
593 // 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 +0000594 // specific here: See definition of state changes: some states are excluded from reset for possible later commit
mpagenkoa2b288f2021-10-21 11:25:27 +0000595 pAdaptFsm = oFsm.PAdaptFsm
mpagenko59862f02021-10-11 08:53:18 +0000596 if pAdaptFsm != nil && pAdaptFsm.PFsm != nil {
mpagenkoc26d4c02021-05-06 14:27:57 +0000597 // calling FSM events in background to avoid blocking of the caller
mpagenko59862f02021-10-11 08:53:18 +0000598 go func(apFsm *fsm.FSM) {
599 if apFsm.Is(UpgradeStWaitEndDL) {
600 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
601 } else if apFsm.Is(UpgradeStAbortingDL) {
602 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //abort waiting on EndDownloadResponse
603 }
mpagenko38662d02021-08-11 09:45:19 +0000604
mpagenko59862f02021-10-11 08:53:18 +0000605 var err error
606 if abCompleteAbort {
607 // in case of unconditional abort request the ImageState is set immediately
608 oFsm.mutexUpgradeParams.Lock()
609 //any previous lingering conditional cancelRequest is superseded by this abortion
610 oFsm.conditionalCancelRequested = false
611 oFsm.volthaDownloadReason = aReason
612 oFsm.mutexUpgradeParams.Unlock()
613 err = apFsm.Event(UpgradeEvAbort) //as unconditional default FSM cancellation
614 } else {
615 //at conditional abort request the image states are set when reaching the reset state
mpagenkoa2b288f2021-10-21 11:25:27 +0000616 oFsm.mutexUpgradeParams.Lock()
mpagenko59862f02021-10-11 08:53:18 +0000617 oFsm.conditionalCancelRequested = true
mpagenkoa2b288f2021-10-21 11:25:27 +0000618 oFsm.mutexUpgradeParams.Unlock()
mpagenko59862f02021-10-11 08:53:18 +0000619 err = apFsm.Event(UpgradeEvReset) //as state-conditional default FSM cleanup
620 }
621 if err != nil {
622 //error return is expected in case of conditional request and no state transition
623 logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
624 "device-id": oFsm.deviceID, "error": err})
625 }
mpagenkoa2b288f2021-10-21 11:25:27 +0000626 logger.Debugw(ctx, "OnuUpgradeFsm canceling done", log.Fields{
627 "device-id": oFsm.deviceID})
mpagenko59862f02021-10-11 08:53:18 +0000628 }(pAdaptFsm.PFsm)
mpagenkoa2b288f2021-10-21 11:25:27 +0000629 } else { //the FSM seems already to be in some released state
630 logger.Warnw(ctx, "OnuUpgradeFsm canceling without FSM event", log.Fields{
631 "device-id": oFsm.deviceID})
632 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000633}
634
mpagenko80622a52021-02-09 16:53:23 +0000635func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
636 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
637 "device-id": oFsm.deviceID})
638
639 // start go routine for processing of LockState messages
640 go oFsm.processOmciUpgradeMessages(ctx)
641}
642
Joey Armstrong89c812c2024-01-12 19:00:20 -0500643// enterWaitingAdapterDL state can only be reached with useAPIVersion43
mpagenkoc26d4c02021-05-06 14:27:57 +0000644func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
645 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
646 "device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +0000647 syncChannel := make(chan struct{})
648 go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
649 //block until the wait routine is really blocked on chAdapterDlReady
650 <-syncChannel
mpagenkoc26d4c02021-05-06 14:27:57 +0000651 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
652}
653
mpagenko80622a52021-02-09 16:53:23 +0000654func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
655 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
656 "device-id": oFsm.deviceID})
657
mpagenkoc26d4c02021-05-06 14:27:57 +0000658 var fileLen int64
659 var err error
mpagenkoaa3afe92021-05-21 16:20:58 +0000660 oFsm.mutexUpgradeParams.Lock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000661 if oFsm.useAPIVersion43 {
662 //with the new API structure download to adapter is implicit and we have to wait until the image is available
663 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
664 } else {
665 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
666 }
mpagenkoc497ee32021-11-10 17:30:20 +0000667 if err != nil || fileLen == 0 || fileLen > int64(cMaxUint32) {
mpagenko39b703e2021-08-25 13:38:40 +0000668 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000669 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000670 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
671 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000672 pBaseFsm := oFsm.PAdaptFsm
mpagenko80622a52021-02-09 16:53:23 +0000673 // Can't call FSM Event directly, decoupling it
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000674 go func(a_pAFsm *cmn.AdapterFsm) {
675 _ = a_pAFsm.PFsm.Event(UpgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000676 }(pBaseFsm)
677 return
678 }
679
mpagenkoc26d4c02021-05-06 14:27:57 +0000680 //copy file content to buffer
mpagenkoc497ee32021-11-10 17:30:20 +0000681 var imageBuffer []byte
mpagenkoc26d4c02021-05-06 14:27:57 +0000682 if oFsm.useAPIVersion43 {
mpagenkoc497ee32021-11-10 17:30:20 +0000683 imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +0000684 } else {
mpagenkoc497ee32021-11-10 17:30:20 +0000685 imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
mpagenkoc26d4c02021-05-06 14:27:57 +0000686 }
mpagenko80622a52021-02-09 16:53:23 +0000687 if err != nil {
mpagenko39b703e2021-08-25 13:38:40 +0000688 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000689 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000690 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
691 "device-id": oFsm.deviceID, "error": err})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000692 pBaseFsm := oFsm.PAdaptFsm
mpagenko80622a52021-02-09 16:53:23 +0000693 // Can't call FSM Event directly, decoupling it
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000694 go func(a_pAFsm *cmn.AdapterFsm) {
695 _ = a_pAFsm.PFsm.Event(UpgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000696 }(pBaseFsm)
697 return
698 }
mpagenkoc497ee32021-11-10 17:30:20 +0000699 //provide slice capacity already with the reserve of one section to avoid inflation of the slice to double size at append
Holger Hildebrandt5458d892022-05-31 09:52:06 +0000700 oFsm.imageBuffer = make([]byte, fileLen, fileLen+oFsm.omciDownloadSectionSize)
mpagenkoc497ee32021-11-10 17:30:20 +0000701 //better use a copy of the read image buffer in case the buffer/file is modified from outside,
702 // this also limits the slice len to the expected maximum fileLen
703 copy(oFsm.imageBuffer, imageBuffer)
mpagenko80622a52021-02-09 16:53:23 +0000704
Holger Hildebrandt5458d892022-05-31 09:52:06 +0000705 oFsm.noOfSections = uint32(fileLen / oFsm.omciDownloadSectionSize)
706 if fileLen%oFsm.omciDownloadSectionSize > 0 {
707 // Because the extended message format allows for variable length,
708 // software image sections are only padded in baseline message format
709 if !oFsm.isExtendedOmci {
710 bufferPadding := make([]byte, oFsm.omciDownloadSectionSize-fileLen%oFsm.omciDownloadSectionSize)
711 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
712 oFsm.imageBuffer = append(oFsm.imageBuffer, bufferPadding...)
713 }
mpagenko80622a52021-02-09 16:53:23 +0000714 oFsm.noOfSections++
715 }
716 oFsm.origImageLength = uint32(fileLen)
717 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000718 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000719 "MeId": oFsm.InactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
mpagenko80622a52021-02-09 16:53:23 +0000720 "ImageSize": oFsm.imageLength, "original file size": fileLen})
721 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
mpagenkoaa3afe92021-05-21 16:20:58 +0000722
723 oFsm.mutexUpgradeParams.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +0000724
mpagenkoa2b288f2021-10-21 11:25:27 +0000725 // flush chOnuDlReady
mpagenko39b703e2021-08-25 13:38:40 +0000726 select {
727 case <-oFsm.chOnuDlReady:
728 logger.Debug(ctx, "flushed OnuDlReady channel")
729 default:
730 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000731 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
732
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000733 err = oFsm.pOmciCC.SendStartSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.GetOmciTimeout(), false,
Holger Hildebrandt5458d892022-05-31 09:52:06 +0000734 oFsm.PAdaptFsm.CommChan, oFsm.InactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength, oFsm.isExtendedOmci)
mpagenko80622a52021-02-09 16:53:23 +0000735 if err != nil {
736 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
737 "device-id": oFsm.deviceID, "error": err})
mpagenko45586762021-10-01 08:30:22 +0000738 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000739 return
740 }
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000741 oFsm.isEndSwDlOpen = true
mpagenko80622a52021-02-09 16:53:23 +0000742}
743
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530744//nolint:unparam
mpagenko80622a52021-02-09 16:53:23 +0000745func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
746 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
747 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
mpagenkoa2b288f2021-10-21 11:25:27 +0000748 //use a background routine to send the multiple download sections frames in a loop
mpagenko609a69a2021-12-02 08:12:58 +0000749 // in order to avoid blocking on synchronous event calls for the entire (long) processing time
mpagenkoa2b288f2021-10-21 11:25:27 +0000750 go oFsm.runSwDlSectionWindow(ctx)
751}
mpagenko80622a52021-02-09 16:53:23 +0000752
Joey Armstrong89c812c2024-01-12 19:00:20 -0500753// runSwDlSectionWindow runs a loop to send all DlSection frames of one window in background
754//
755// may be aborted by parallel change of abortRequested
mpagenkoa2b288f2021-10-21 11:25:27 +0000756func (oFsm *OnuUpgradeFsm) runSwDlSectionWindow(ctx context.Context) {
mpagenko80622a52021-02-09 16:53:23 +0000757 var windowAckRequest uint8 = 0
758 var bufferStartOffset uint32
759 var bufferEndOffset uint32
760 var downloadSection []byte
kesavand011d5162021-11-25 19:21:06 +0530761
mpagenkoaa3afe92021-05-21 16:20:58 +0000762 oFsm.mutexUpgradeParams.Lock()
mpagenko45586762021-10-01 08:30:22 +0000763 oFsm.upgradePhase = cUpgradeDownloading //start of downloading image to ONU
mpagenko80622a52021-02-09 16:53:23 +0000764 if oFsm.nextDownloadSectionsAbsolute == 0 {
mpagenkoaa3afe92021-05-21 16:20:58 +0000765 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
mpagenko80622a52021-02-09 16:53:23 +0000766 }
kesavand011d5162021-11-25 19:21:06 +0530767 //var omuTxSecPerWindow []*common.OmciTransferStructure
768 omciMsgsPerSection := &ia.OmciMessages{}
769 //take the TID mutex
770 //To ensure the insequesnce of TIDS for all the onusw sections within a window
771 oFsm.pOmciCC.LockMutexTID()
772 defer oFsm.pOmciCC.UnLockMutexTID()
mpagenko80622a52021-02-09 16:53:23 +0000773 for {
mpagenko38662d02021-08-11 09:45:19 +0000774 oFsm.mutexAbortRequest.RLock()
775 // this way out of the section download loop on abort request
776 if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
mpagenko45586762021-10-01 08:30:22 +0000777 //states are updated when entering the reset state ...
mpagenko38662d02021-08-11 09:45:19 +0000778 oFsm.volthaDownloadReason = oFsm.abortRequested
779 oFsm.mutexAbortRequest.RUnlock()
780 oFsm.mutexUpgradeParams.Unlock()
mpagenkoa2b288f2021-10-21 11:25:27 +0000781 pUpgradeFsm := oFsm.PAdaptFsm
782 if pUpgradeFsm != nil {
783 _ = pUpgradeFsm.PFsm.Event(UpgradeEvAbort)
784 logger.Debugw(ctx, "aborting runSwDlSectionWindow", log.Fields{
785 "device-id": oFsm.deviceID, "reason": oFsm.volthaDownloadReason})
786 return
787 }
788 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +0000789 return
790 }
791 oFsm.mutexAbortRequest.RUnlock()
792
Holger Hildebrandt5458d892022-05-31 09:52:06 +0000793 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * uint32(oFsm.omciDownloadSectionSize)
794 bufferEndOffset = bufferStartOffset + uint32(oFsm.omciDownloadSectionSize) - 1
795 if oFsm.isExtendedOmci {
796 if bufferEndOffset > oFsm.origImageLength-1 {
797 bufferEndOffset = oFsm.origImageLength - 1
798 }
799 }
mpagenko80622a52021-02-09 16:53:23 +0000800 logger.Debugw(ctx, "DlSection values are", log.Fields{
801 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
802 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
803 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
804 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
805 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
806 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
807 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
mpagenko39b703e2021-08-25 13:38:40 +0000808 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000809 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000810 //logical error -- reset the FSM
mpagenkoa2b288f2021-10-21 11:25:27 +0000811 pUpgradeFsm := oFsm.PAdaptFsm
812 if pUpgradeFsm != nil {
813 _ = pUpgradeFsm.PFsm.Event(UpgradeEvAbort)
814 return
815 }
816 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000817 return
818 }
819 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
820 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
821 windowAckRequest = 1
822 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
823 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
824 }
825 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
826 windowAckRequest = 1
kesavand011d5162021-11-25 19:21:06 +0530827
mpagenko15ff4a52021-03-02 10:09:20 +0000828 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
829 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000830 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
831 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000832 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
kesavand011d5162021-11-25 19:21:06 +0530833 omciTxReq, err := oFsm.pOmciCC.PrepareOnuSectionsOfWindow(log.WithSpanFromContext(context.Background(), ctx),
Holger Hildebrandt5458d892022-05-31 09:52:06 +0000834 oFsm.InactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, omciMsgsPerSection, oFsm.isExtendedOmci)
mpagenko80622a52021-02-09 16:53:23 +0000835 if err != nil {
836 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000837 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenkoa2b288f2021-10-21 11:25:27 +0000838 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +0000839 return
840 }
kesavand011d5162021-11-25 19:21:06 +0530841
mpagenkoaa3afe92021-05-21 16:20:58 +0000842 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000843 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
844 if windowAckRequest == 1 {
mpagenkoaa3afe92021-05-21 16:20:58 +0000845 oFsm.mutexUpgradeParams.Unlock()
kesavand011d5162021-11-25 19:21:06 +0530846
847 if omciTxReq.OnuSwWindow == nil {
848 logger.Errorw(ctx, "fail to send sections in a window", log.Fields{
849 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
850 oFsm.abortOnOmciError(ctx, false)
851 return
852 }
853
mpagenkoa2b288f2021-10-21 11:25:27 +0000854 pUpgradeFsm := oFsm.PAdaptFsm
855 if pUpgradeFsm != nil {
856 _ = pUpgradeFsm.PFsm.Event(UpgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
Balaji Seenivasana52fb0c2024-12-18 07:50:42 +0530857 err := oFsm.pOmciCC.SendOnuSwSectionsWindowWithRxSupervision(ctx, omciTxReq, oFsm.pDeviceHandler.GetOmciTimeout(), oFsm.PAdaptFsm.CommChan)
858 if err != nil {
859 logger.Errorw(ctx, "DlSection abort: can't send window acknowledgement request to ONU ", log.Fields{
860 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
861 oFsm.abortOnOmciError(ctx, false)
862 }
mpagenkoa2b288f2021-10-21 11:25:27 +0000863 return
864 }
865 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000866 return
867 }
kesavand011d5162021-11-25 19:21:06 +0530868
mpagenko80622a52021-02-09 16:53:23 +0000869 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000870 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000871 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenkoaa3afe92021-05-21 16:20:58 +0000872 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko59498c12021-03-18 14:15:15 +0000873 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenkoaa3afe92021-05-21 16:20:58 +0000874 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000875 }
876 }
mpagenkoa2b288f2021-10-21 11:25:27 +0000877} //runSwDlSectionWindow
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530878//nolint:unparam
mpagenko80622a52021-02-09 16:53:23 +0000879func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
880 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
881 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
882}
883
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530884//nolint:unparam
mpagenko80622a52021-02-09 16:53:23 +0000885func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000886 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000887 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
mpagenko609a69a2021-12-02 08:12:58 +0000888 //use a background routine to wait EndSwDlDelay and then send the EndSwDl request
889 // in order to avoid blocking on synchronous event calls for the complete wait time
890 // and to allow for state transition before sending the EndSwDl request
891 go oFsm.delayAndSendEndSwDl(ctx)
892}
mpagenko80622a52021-02-09 16:53:23 +0000893
Joey Armstrong89c812c2024-01-12 19:00:20 -0500894// delayAndSendEndSwDl ensures a delay before sending the EndSwDl request
895//
896// may also be aborted by parallel channel reception on chAbortEndSwDl
mpagenko609a69a2021-12-02 08:12:58 +0000897func (oFsm *OnuUpgradeFsm) delayAndSendEndSwDl(ctx context.Context) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000898 oFsm.mutexUpgradeParams.RLock()
mpagenko80622a52021-02-09 16:53:23 +0000899 if oFsm.delayEndSwDl {
mpagenkoaa3afe92021-05-21 16:20:58 +0000900 oFsm.mutexUpgradeParams.RUnlock()
mpagenko609a69a2021-12-02 08:12:58 +0000901 //give the ONU some time for image evaluation (hoping it does not only start this evaluation on first EndSwDl itself)
902 logger.Debugw(ctx, "OnuUpgradeFsm delay EndSwDl", log.Fields{"device-id": oFsm.deviceID,
903 "duration_s": cOmciEndSwDlDelaySeconds})
904 select {
905 case <-time.After(cOmciEndSwDlDelaySeconds * time.Second):
906 logger.Warnw(ctx, "OnuUpgradeFsm start sending EndSwDl", log.Fields{
907 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier})
908 case <-oFsm.chAbortDelayEndSwDl:
909 logger.Debugw(ctx, "OnuUpgradeFsm abort request to send EndSwDl", log.Fields{"device-id": oFsm.deviceID})
910 //according further state transition is ensured by the entity that sent the abort
911 return
912 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000913 } else {
914 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000915 }
916
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000917 pBaseFsm := oFsm.PAdaptFsm
mpagenko59498c12021-03-18 14:15:15 +0000918 if pBaseFsm == nil {
mpagenko38662d02021-08-11 09:45:19 +0000919 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
920 oFsm.mutexUpgradeParams.Lock()
mpagenko38662d02021-08-11 09:45:19 +0000921 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
922 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000923 // Can't call FSM Event directly, decoupling it
mpagenko609a69a2021-12-02 08:12:58 +0000924 _ = pBaseFsm.PFsm.Event(UpgradeEvAbort)
mpagenko59498c12021-03-18 14:15:15 +0000925 return
926 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000927 err := oFsm.pOmciCC.SendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.GetOmciTimeout(), false,
Holger Hildebrandt5458d892022-05-31 09:52:06 +0000928 oFsm.PAdaptFsm.CommChan, oFsm.InactiveImageMeID, oFsm.origImageLength, oFsm.imageCRC, oFsm.isExtendedOmci)
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000929
mpagenko80622a52021-02-09 16:53:23 +0000930 if err != nil {
mpagenkoa2b288f2021-10-21 11:25:27 +0000931 logger.Errorw(ctx, "EndSwDl abort: error sending EndSwDl", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000932 "device-id": oFsm.deviceID, "error": err})
mpagenko45586762021-10-01 08:30:22 +0000933 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000934 return
935 }
mpagenko609a69a2021-12-02 08:12:58 +0000936 //from here on sending of EndSwDl(Abort) is not needed anymore (even though response is not yet received)
937 // this avoids sending of both EndSwDl(Success) and EndSwDl(Abort) when cancellation falls just into this window
938 // the ONU must theoretically be prepared to receive none of them (in case of OMCI transfer issues) e.g. by timeout
939 oFsm.isEndSwDlOpen = false
940 // wait for the EndSwDLResponse and check, if the ONU is ready for activation
941 _ = pBaseFsm.PFsm.Event(UpgradeEvWaitEndDownload)
942} //delayAndSendEndSwDl
mpagenko59498c12021-03-18 14:15:15 +0000943
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530944//nolint:unparam
mpagenko59498c12021-03-18 14:15:15 +0000945func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
946 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
947 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
948 if oFsm.waitCountEndSwDl == 0 {
949 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
950 "device-id": oFsm.deviceID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000951 pBaseFsm := oFsm.PAdaptFsm
mpagenko59498c12021-03-18 14:15:15 +0000952 if pBaseFsm == nil {
953 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
954 "device-id": oFsm.deviceID})
955 return
956 }
mpagenko38662d02021-08-11 09:45:19 +0000957 oFsm.mutexUpgradeParams.Lock()
mpagenko39b703e2021-08-25 13:38:40 +0000958 oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
mpagenko38662d02021-08-11 09:45:19 +0000959 oFsm.mutexUpgradeParams.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000960 go func(a_pAFsm *cmn.AdapterFsm) {
961 _ = a_pAFsm.PFsm.Event(UpgradeEvAbort)
mpagenko59498c12021-03-18 14:15:15 +0000962 }(pBaseFsm)
963 return
964 }
965
966 oFsm.waitCountEndSwDl--
967 select {
968 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000969 pBaseFsm := oFsm.PAdaptFsm
mpagenko59498c12021-03-18 14:15:15 +0000970 if pBaseFsm == nil {
971 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
972 "device-id": oFsm.deviceID})
973 //FSM may be reset already from somewhere else, nothing we can do here anymore
974 return
975 }
976 //retry End SW DL
mpagenkoaa3afe92021-05-21 16:20:58 +0000977 oFsm.mutexUpgradeParams.Lock()
mpagenko59498c12021-03-18 14:15:15 +0000978 oFsm.delayEndSwDl = false //no more extra delay for the request
mpagenkoaa3afe92021-05-21 16:20:58 +0000979 oFsm.mutexUpgradeParams.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000980 go func(a_pAFsm *cmn.AdapterFsm) {
981 _ = a_pAFsm.PFsm.Event(UpgradeEvContinueFinalize)
mpagenko59498c12021-03-18 14:15:15 +0000982 }(pBaseFsm)
983 return
984 case success := <-oFsm.chReceiveExpectedResponse:
985 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
mpagenko45586762021-10-01 08:30:22 +0000986 oFsm.isEndSwDlOpen = false //no request to abort of download (already finished or immediate abort)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000987 pBaseFsm := oFsm.PAdaptFsm
mpagenko59498c12021-03-18 14:15:15 +0000988 if pBaseFsm == nil {
989 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
990 "device-id": oFsm.deviceID})
991 //FSM may be reset already from somewhere else, nothing we can do here anymore
992 return
993 }
994 if success {
995 //answer received with ready indication
mpagenko38662d02021-08-11 09:45:19 +0000996 //useAPIVersion43 may not conflict in concurrency in this state function
997 if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000998 go func(a_pAFsm *cmn.AdapterFsm) {
999 _ = a_pAFsm.PFsm.Event(UpgradeEvCheckImageName)
mpagenkoc26d4c02021-05-06 14:27:57 +00001000 }(pBaseFsm)
mpagenko38662d02021-08-11 09:45:19 +00001001 } else { // elder API usage does not support image version check -immediately consider download as successful
1002 if oFsm.activateImage {
1003 //immediate activation requested
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001004 go func(a_pAFsm *cmn.AdapterFsm) {
1005 _ = a_pAFsm.PFsm.Event(UpgradeEvRequestActivate)
mpagenko38662d02021-08-11 09:45:19 +00001006 }(pBaseFsm)
1007 } else {
1008 //have to wait on explicit activation request
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001009 go func(a_pAFsm *cmn.AdapterFsm) {
1010 _ = a_pAFsm.PFsm.Event(UpgradeEvWaitForActivate)
mpagenko38662d02021-08-11 09:45:19 +00001011 }(pBaseFsm)
1012 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001013 }
mpagenko59498c12021-03-18 14:15:15 +00001014 return
1015 }
1016 //timer was aborted
mpagenko45586762021-10-01 08:30:22 +00001017 oFsm.abortOnOmciError(ctx, true)
mpagenko59498c12021-03-18 14:15:15 +00001018 return
1019 }
mpagenko80622a52021-02-09 16:53:23 +00001020}
1021
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301022//nolint:unparam
mpagenko38662d02021-08-11 09:45:19 +00001023func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
1024 logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001025 "device-id": oFsm.deviceID, "me-id": oFsm.InactiveImageMeID})
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001026 requestedAttributes := me.AttributeValueMap{me.SoftwareImage_IsCommitted: 0, me.SoftwareImage_IsActive: 0, me.SoftwareImage_Version: ""}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001027 meInstance, err := oFsm.pOmciCC.SendGetMe(log.WithSpanFromContext(context.Background(), ctx),
1028 me.SoftwareImageClassID, oFsm.InactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.GetOmciTimeout(),
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001029 false, oFsm.PAdaptFsm.CommChan, oFsm.isExtendedOmci)
mpagenko38662d02021-08-11 09:45:19 +00001030 if err != nil {
1031 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
1032 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko45586762021-10-01 08:30:22 +00001033 oFsm.abortOnOmciError(ctx, true)
mpagenko38662d02021-08-11 09:45:19 +00001034 return
1035 }
1036 oFsm.pLastTxMeInstance = meInstance
1037}
1038
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301039//nolint:unparam
mpagenko80622a52021-02-09 16:53:23 +00001040func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
1041 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001042 "device-id": oFsm.deviceID, "me-id": oFsm.InactiveImageMeID})
mpagenko80622a52021-02-09 16:53:23 +00001043
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001044 err := oFsm.pOmciCC.SendActivateSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.GetOmciTimeout(), false,
Holger Hildebrandt5458d892022-05-31 09:52:06 +00001045 oFsm.PAdaptFsm.CommChan, oFsm.InactiveImageMeID, oFsm.isExtendedOmci)
mpagenko80622a52021-02-09 16:53:23 +00001046 if err != nil {
1047 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
1048 "device-id": oFsm.deviceID, "error": err})
mpagenko45586762021-10-01 08:30:22 +00001049 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +00001050 return
1051 }
mpagenko38662d02021-08-11 09:45:19 +00001052 oFsm.mutexUpgradeParams.Lock()
mpagenko45586762021-10-01 08:30:22 +00001053 oFsm.upgradePhase = cUpgradeActivating //start of image activation for ONU
mpagenko38662d02021-08-11 09:45:19 +00001054 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
1055 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001056}
1057
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301058//nolint:unparam
mpagenko80622a52021-02-09 16:53:23 +00001059func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +00001060 logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001061 "device-id": oFsm.deviceID, "me-id": oFsm.InactiveImageMeID})
mpagenko38662d02021-08-11 09:45:19 +00001062 //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
1063 // (which is a bit problematic as the ONU might already be in committed state,
1064 // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
1065 if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
mpagenkoaa3afe92021-05-21 16:20:58 +00001066 oFsm.mutexUpgradeParams.Lock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001067 if activeImageID == oFsm.InactiveImageMeID {
1068 inactiveImageID := oFsm.InactiveImageMeID
mpagenko15ff4a52021-03-02 10:09:20 +00001069 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
mpagenkoaa3afe92021-05-21 16:20:58 +00001070 "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
1071 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
mpagenko45586762021-10-01 08:30:22 +00001072 oFsm.upgradePhase = cUpgradeCommitting //start of image commitment for ONU
mpagenkoaa3afe92021-05-21 16:20:58 +00001073 oFsm.mutexUpgradeParams.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001074 err := oFsm.pOmciCC.SendCommitSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.GetOmciTimeout(), false,
Holger Hildebrandt5458d892022-05-31 09:52:06 +00001075 oFsm.PAdaptFsm.CommChan, inactiveImageID, oFsm.isExtendedOmci) //more efficient activeImageID with above check
mpagenko15ff4a52021-03-02 10:09:20 +00001076 if err != nil {
1077 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
1078 "device-id": oFsm.deviceID, "error": err})
mpagenko45586762021-10-01 08:30:22 +00001079 oFsm.abortOnOmciError(ctx, true)
mpagenko15ff4a52021-03-02 10:09:20 +00001080 return
1081 }
1082 return
1083 }
mpagenko38662d02021-08-11 09:45:19 +00001084 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001085 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001086 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.InactiveImageMeID})
mpagenko38662d02021-08-11 09:45:19 +00001087 } else {
1088 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
1089 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +00001090 }
mpagenko38662d02021-08-11 09:45:19 +00001091 oFsm.mutexUpgradeParams.Lock()
1092 oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
mpagenko38662d02021-08-11 09:45:19 +00001093 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
mpagenko38662d02021-08-11 09:45:19 +00001094 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001095 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001096 pBaseFsm := oFsm.PAdaptFsm
mpagenko15ff4a52021-03-02 10:09:20 +00001097 // Can't call FSM Event directly, decoupling it
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001098 go func(a_pAFsm *cmn.AdapterFsm) {
1099 _ = a_pAFsm.PFsm.Event(UpgradeEvAbort)
mpagenko15ff4a52021-03-02 10:09:20 +00001100 }(pBaseFsm)
1101}
1102
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301103//nolint:unparam
mpagenko15ff4a52021-03-02 10:09:20 +00001104func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +00001105 logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001106 "device-id": oFsm.deviceID, "me-id": oFsm.InactiveImageMeID})
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001107 requestedAttributes := me.AttributeValueMap{me.SoftwareImage_IsCommitted: 0, me.SoftwareImage_IsActive: 0, me.SoftwareImage_Version: ""}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001108 meInstance, err := oFsm.pOmciCC.SendGetMe(log.WithSpanFromContext(context.Background(), ctx),
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001109 me.SoftwareImageClassID, oFsm.InactiveImageMeID, requestedAttributes,
1110 oFsm.pDeviceHandler.GetOmciTimeout(), false, oFsm.PAdaptFsm.CommChan, oFsm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001111 if err != nil {
1112 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
1113 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko45586762021-10-01 08:30:22 +00001114 oFsm.abortOnOmciError(ctx, true)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001115 return
1116 }
mpagenko15ff4a52021-03-02 10:09:20 +00001117 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +00001118}
1119
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301120//nolint:unparam
mpagenko80622a52021-02-09 16:53:23 +00001121func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1122 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
1123
mpagenko45586762021-10-01 08:30:22 +00001124 oFsm.stateUpdateOnReset(ctx)
mpagenko38662d02021-08-11 09:45:19 +00001125
mpagenkoa2b288f2021-10-21 11:25:27 +00001126 oFsm.mutexAbortRequest.Lock()
1127 //to be sure to abort a possibly still running runSwDlSectionWindow()
1128 // in case the reset was not received from cancel() and download not finished correctly
1129 oFsm.abortRequested = oFsm.volthaDownloadReason
1130 oFsm.mutexAbortRequest.Unlock()
1131
mpagenkoc26d4c02021-05-06 14:27:57 +00001132 // in case the download-to-ONU timer is still running - cancel it
mpagenko39b703e2021-08-25 13:38:40 +00001133 //use non-blocking channel (to be independent from receiver state)
1134 select {
1135 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1136 case oFsm.chOnuDlReady <- false:
1137 default:
mpagenkoc26d4c02021-05-06 14:27:57 +00001138 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001139 pConfigUpgradeStateAFsm := oFsm.PAdaptFsm
1140 if pConfigUpgradeStateAFsm != nil {
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001141 var nextEvent string
1142 if oFsm.isEndSwDlOpen {
mpagenko45586762021-10-01 08:30:22 +00001143 if oFsm.repeatAbort {
1144 oFsm.delayEndSwDl = true //run next abort with delay
1145 } else { //initial request
1146 oFsm.delayEndSwDl = false //run next abort with no delay
1147 oFsm.waitCountEndSwDl = cWaitCountEndSwDl //init for possible repetitions
1148 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001149 nextEvent = UpgradeEvAbortSwDownload
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001150 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001151 nextEvent = UpgradeEvRestart
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001152 }
1153 // Can't call FSM Event directly, decoupling it
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001154 go func(a_pAFsm *cmn.AdapterFsm) {
1155 if a_pAFsm != nil && a_pAFsm.PFsm != nil {
1156 _ = a_pAFsm.PFsm.Event(nextEvent)
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001157 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001158 }(pConfigUpgradeStateAFsm)
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001159 }
1160}
mpagenkoc26d4c02021-05-06 14:27:57 +00001161
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301162//nolint:unparam
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001163func (oFsm *OnuUpgradeFsm) enterAbortingDL(ctx context.Context, e *fsm.Event) {
1164 logger.Debugw(ctx, "OnuUpgradeFsm aborting download to ONU", log.Fields{"device-id": oFsm.deviceID})
1165
mpagenko45586762021-10-01 08:30:22 +00001166 oFsm.mutexUpgradeParams.RLock()
1167 if oFsm.delayEndSwDl {
1168 oFsm.mutexUpgradeParams.RUnlock()
1169 //give the ONU some time for image discard activities
1170 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
1171 } else {
1172 oFsm.mutexUpgradeParams.RUnlock()
1173 }
1174
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001175 pBaseFsm := oFsm.PAdaptFsm
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001176 if pBaseFsm == nil {
1177 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
1178 return
1179 }
1180 // abort the download operation by sending an end software download message with invalid CRC and image size
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001181 err := oFsm.pOmciCC.SendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.GetOmciTimeout(), false,
Holger Hildebrandt5458d892022-05-31 09:52:06 +00001182 oFsm.PAdaptFsm.CommChan, oFsm.InactiveImageMeID, 0, 0xFFFFFFFF, oFsm.isExtendedOmci)
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001183
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001184 if err != nil {
1185 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: can't send EndSwDl request", log.Fields{"device-id": oFsm.deviceID})
1186 // Can't call FSM Event directly, decoupling it
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001187 go func(a_pAFsm *cmn.AdapterFsm) {
1188 if a_pAFsm != nil && a_pAFsm.PFsm != nil {
1189 _ = a_pAFsm.PFsm.Event(UpgradeEvRestart)
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001190 }
1191 }(pBaseFsm)
1192 return
1193 }
mpagenkoa2b288f2021-10-21 11:25:27 +00001194
1195 //avoid waiting in the enterXXX function here,
1196 // otherwise synchronous event calls (like from RxMessage processing) may block and block complete Rx processing then
1197 go oFsm.waitOnAbortEndSwDlResponse(ctx)
mpagenko45586762021-10-01 08:30:22 +00001198}
1199
Joey Armstrong89c812c2024-01-12 19:00:20 -05001200// abortingDlEvaluateResponse waits for a channel indication with decision to proceed the FSM processing
mpagenko45586762021-10-01 08:30:22 +00001201func (oFsm *OnuUpgradeFsm) abortingDlEvaluateResponse(ctx context.Context,
1202 pBaseFsm *cmn.AdapterFsm, aResponseResult tEndSwDlResponseResult) bool {
1203 switch aResponseResult {
1204 case cEndSwDlResponseBusy: // indication for device busy, needs repetition
1205 if oFsm.waitCountEndSwDl == 0 {
1206 logger.Errorw(ctx, "aborting download: max limit of EndSwDl reached", log.Fields{
1207 "device-id": oFsm.deviceID})
1208 go func(a_pAFsm *cmn.AdapterFsm) {
1209 if a_pAFsm != nil && a_pAFsm.PFsm != nil {
1210 _ = a_pAFsm.PFsm.Event(UpgradeEvRestart) //give up and let FSM terminate
1211 }
1212 }(pBaseFsm)
1213 } else {
1214 logger.Debugw(ctx, "aborting download: re-trigger sending abort SwDl", log.Fields{
1215 "device-id": oFsm.deviceID, "counter": oFsm.waitCountEndSwDl})
1216 oFsm.waitCountEndSwDl--
1217 oFsm.repeatAbort = true //repeated request in next round
1218 go func(a_pAFsm *cmn.AdapterFsm) {
1219 if a_pAFsm != nil && a_pAFsm.PFsm != nil {
1220 _ = a_pAFsm.PFsm.Event(UpgradeEvReset) //which then re-triggers sending AbortSwDL
1221 }
1222 }(pBaseFsm)
1223 }
1224 return true
1225 case cEndSwDlResponseSuccess: // indication for success response
1226 logger.Infow(ctx, "aborting download: success response, terminating FSM", log.Fields{
1227 "device-id": oFsm.deviceID})
1228 case cEndSwDlResponseAbort: // indication for request to abort waiting for response
1229 logger.Infow(ctx, "aborting download: request to abort waiting, terminating FSM", log.Fields{
1230 "device-id": oFsm.deviceID})
1231 default:
1232 logger.Errorw(ctx, "aborting download: unknown channel indication, terminating FSM", log.Fields{
1233 "device-id": oFsm.deviceID})
1234 } //switch
1235 return false
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001236}
1237
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301238//nolint:unparam
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001239func (oFsm *OnuUpgradeFsm) enterRestarting(ctx context.Context, e *fsm.Event) {
1240 logger.Debugw(ctx, "OnuUpgradeFsm restarting", log.Fields{"device-id": oFsm.deviceID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001241 pConfigUpgradeStateAFsm := oFsm.PAdaptFsm
1242 if pConfigUpgradeStateAFsm != nil {
mpagenko80622a52021-02-09 16:53:23 +00001243 // abort running message processing
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001244 fsmAbortMsg := cmn.Message{
1245 Type: cmn.TestMsg,
1246 Data: cmn.TestMessage{
1247 TestMessageVal: cmn.AbortMessageProcessing,
mpagenko80622a52021-02-09 16:53:23 +00001248 },
1249 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001250 pConfigUpgradeStateAFsm.CommChan <- fsmAbortMsg
mpagenko80622a52021-02-09 16:53:23 +00001251
1252 //try to restart the FSM to 'disabled'
1253 // Can't call FSM Event directly, decoupling it
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001254 go func(a_pAFsm *cmn.AdapterFsm) {
1255 if a_pAFsm != nil && a_pAFsm.PFsm != nil {
1256 _ = a_pAFsm.PFsm.Event(UpgradeEvDisable)
mpagenko80622a52021-02-09 16:53:23 +00001257 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001258 }(pConfigUpgradeStateAFsm)
mpagenko80622a52021-02-09 16:53:23 +00001259 }
1260}
1261
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301262//nolint:unparam
mpagenko80622a52021-02-09 16:53:23 +00001263func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1264 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001265 // 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 +00001266 if oFsm.pDeviceHandler != nil {
1267 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenko38662d02021-08-11 09:45:19 +00001268 pLastUpgradeImageState := &voltha.ImageState{
1269 Version: oFsm.imageVersion,
1270 DownloadState: oFsm.volthaDownloadState,
1271 Reason: oFsm.volthaDownloadReason,
1272 ImageState: oFsm.volthaImageState,
1273 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001274 go oFsm.pDeviceHandler.RemoveOnuUpgradeFsm(ctx, pLastUpgradeImageState)
mpagenko80622a52021-02-09 16:53:23 +00001275 }
1276}
1277
1278func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
1279 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
1280loop:
1281 for {
1282 // case <-ctx.Done():
1283 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
1284 // break loop
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001285 message, ok := <-oFsm.PAdaptFsm.CommChan
mpagenko80622a52021-02-09 16:53:23 +00001286 if !ok {
1287 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
1288 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko45586762021-10-01 08:30:22 +00001289 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +00001290 break loop
1291 }
1292 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
1293
1294 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001295 case cmn.TestMsg:
1296 msg, _ := message.Data.(cmn.TestMessage)
1297 if msg.TestMessageVal == cmn.AbortMessageProcessing {
mpagenko80622a52021-02-09 16:53:23 +00001298 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
1299 break loop
1300 }
1301 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001302 case cmn.OMCI:
1303 msg, _ := message.Data.(cmn.OmciMessage)
mpagenko80622a52021-02-09 16:53:23 +00001304 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
1305 default:
1306 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
1307 "message.Type": message.Type})
1308 }
1309 }
1310 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
1311}
1312
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001313func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg cmn.OmciMessage) {
mpagenko80622a52021-02-09 16:53:23 +00001314 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
1315 "msgType": msg.OmciMsg.MessageType})
1316
1317 switch msg.OmciMsg.MessageType {
1318 case omci.StartSoftwareDownloadResponseType:
1319 {
mpagenko45586762021-10-01 08:30:22 +00001320 oFsm.handleRxStartSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001321 return
1322 } //StartSoftwareDownloadResponseType
1323 case omci.DownloadSectionResponseType:
1324 {
mpagenko45586762021-10-01 08:30:22 +00001325 oFsm.handleRxSwSectionResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001326 return
mpagenko80622a52021-02-09 16:53:23 +00001327 } //DownloadSectionResponseType
1328 case omci.EndSoftwareDownloadResponseType:
1329 {
mpagenko45586762021-10-01 08:30:22 +00001330 oFsm.handleRxEndSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001331 return
1332 } //EndSoftwareDownloadResponseType
1333 case omci.ActivateSoftwareResponseType:
1334 {
1335 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1336 if msgLayer == nil {
1337 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1338 log.Fields{"device-id": oFsm.deviceID})
mpagenko45586762021-10-01 08:30:22 +00001339 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001340 return
1341 }
1342 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1343 if !msgOk {
1344 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1345 log.Fields{"device-id": oFsm.deviceID})
mpagenko45586762021-10-01 08:30:22 +00001346 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001347 return
1348 }
1349 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1350 "device-id": oFsm.deviceID, "data-fields": msgObj})
1351 if msgObj.Result != me.Success {
1352 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1353 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko45586762021-10-01 08:30:22 +00001354 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001355 return
1356 }
mpagenko183647c2021-06-08 15:25:04 +00001357 oFsm.mutexUpgradeParams.Lock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001358 if msgObj.EntityInstance == oFsm.InactiveImageMeID {
mpagenko38662d02021-08-11 09:45:19 +00001359 // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
mpagenko183647c2021-06-08 15:25:04 +00001360 oFsm.mutexUpgradeParams.Unlock()
1361 logger.Infow(ctx, "Expected ActivateSwResponse received",
1362 log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
1363 if oFsm.commitImage {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001364 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvWaitForCommit)
mpagenko183647c2021-06-08 15:25:04 +00001365 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001366 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvActivationDone) // let the FSM wait for external commit request
mpagenko183647c2021-06-08 15:25:04 +00001367 }
mpagenko80622a52021-02-09 16:53:23 +00001368 return
1369 }
mpagenko183647c2021-06-08 15:25:04 +00001370 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001371 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1372 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko45586762021-10-01 08:30:22 +00001373 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001374 return
1375 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001376 case omci.CommitSoftwareResponseType:
1377 {
1378 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1379 if msgLayer == nil {
1380 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1381 log.Fields{"device-id": oFsm.deviceID})
mpagenko45586762021-10-01 08:30:22 +00001382 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001383 return
1384 }
1385 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1386 if !msgOk {
1387 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1388 log.Fields{"device-id": oFsm.deviceID})
mpagenko45586762021-10-01 08:30:22 +00001389 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001390 return
1391 }
mpagenkobf67a092021-03-17 09:52:28 +00001392 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001393 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1394 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko45586762021-10-01 08:30:22 +00001395 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001396 return
mpagenkobf67a092021-03-17 09:52:28 +00001397 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001398 oFsm.mutexUpgradeParams.RLock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001399 if msgObj.EntityInstance == oFsm.InactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001400 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001401 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1402 //verifying committed image
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001403 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvCheckCommitted)
mpagenko15ff4a52021-03-02 10:09:20 +00001404 return
1405 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001406 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001407 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1408 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko45586762021-10-01 08:30:22 +00001409 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001410 return
1411 } //CommitSoftwareResponseType
1412 case omci.GetResponseType:
1413 {
mpagenko45586762021-10-01 08:30:22 +00001414 oFsm.handleRxSwGetResponse(ctx, msg)
mpagenko15ff4a52021-03-02 10:09:20 +00001415 return
1416 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001417 default:
1418 {
1419 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1420 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1421 return
1422 }
1423 }
1424}
1425
mpagenko45586762021-10-01 08:30:22 +00001426func (oFsm *OnuUpgradeFsm) handleRxStartSwDownloadResponse(ctx context.Context, msg cmn.OmciMessage) {
1427 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
1428 if msgLayer == nil {
1429 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
1430 log.Fields{"device-id": oFsm.deviceID})
1431 oFsm.abortOnOmciError(ctx, false)
1432 return
1433 }
1434 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
1435 if !msgOk {
1436 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
1437 log.Fields{"device-id": oFsm.deviceID})
1438 oFsm.abortOnOmciError(ctx, false)
1439 return
1440 }
1441 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
1442 "device-id": oFsm.deviceID, "data-fields": msgObj})
1443 if msgObj.Result != me.Success {
1444 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
1445 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1446 oFsm.abortOnOmciError(ctx, false)
1447 return
1448 }
1449
1450 oFsm.mutexUpgradeParams.Lock()
1451 if msgObj.EntityInstance == oFsm.InactiveImageMeID {
1452 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1453 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
1454 // also response WindowSize = 0 is a valid number for used Window size 1
1455 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
1456 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
1457 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
1458 }
1459 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
1460 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
1461 oFsm.noOfWindows++
1462 }
1463 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
1464 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
1465 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
1466 oFsm.nextDownloadSectionsAbsolute = 0
1467 oFsm.nextDownloadSectionsWindow = 0
1468 oFsm.nextDownloadWindow = 0
1469
1470 oFsm.mutexUpgradeParams.Unlock()
1471 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvRxStartSwDownload)
1472 return
1473 }
1474 oFsm.mutexUpgradeParams.Unlock()
1475 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1476 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1477 oFsm.abortOnOmciError(ctx, false)
1478} //handleRxStartSwDownloadResponse
1479
1480func (oFsm *OnuUpgradeFsm) handleRxSwSectionResponse(ctx context.Context, msg cmn.OmciMessage) {
mpagenkoa2b288f2021-10-21 11:25:27 +00001481 if oFsm.PAdaptFsm == nil {
1482 logger.Infow(ctx, "DlSectionResponse received - but FSM not really valid anymore", log.Fields{
1483 "device-id": oFsm.deviceID})
1484 return
1485 }
1486 if !oFsm.PAdaptFsm.PFsm.Is(UpgradeStVerifyWindow) {
1487 //all the processing here is only relevant if the FSM is in state upgradeStVerifyWindow
1488 // otherwise this response can be ignored (may stem from a long-processing window send activity,
1489 // which is not anymore relevant based on intermediate (cancel) state transitions)
1490 logger.Infow(ctx, "DlSectionResponse received - but ignored", log.Fields{
1491 "device-id": oFsm.deviceID, "fsm-state": oFsm.PAdaptFsm.PFsm.Current()})
1492 return
1493 }
mpagenko45586762021-10-01 08:30:22 +00001494 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
1495 if msgLayer == nil {
1496 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
1497 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
1498 oFsm.abortOnOmciError(ctx, false)
1499 return
1500 }
1501 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
1502 if !msgOk {
1503 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
1504 log.Fields{"device-id": oFsm.deviceID})
1505 oFsm.abortOnOmciError(ctx, false)
1506 return
1507 }
1508 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
1509 "device-id": oFsm.deviceID, "data-fields": msgObj})
1510 if msgObj.Result != me.Success {
mgouda2b946fd2025-06-16 17:54:21 +05301511 logger.Warnf(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?",
mpagenko45586762021-10-01 08:30:22 +00001512 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mgouda2b946fd2025-06-16 17:54:21 +05301513 if msgObj.Result == me.ProcessingError {
1514 oFsm.currentErrState = ResultErr
1515 oFsm.mutexUpgradeParams.Lock()
1516 oFsm.retrySoftwareDownload(ctx)
1517 return
1518 }
mpagenko45586762021-10-01 08:30:22 +00001519 oFsm.abortOnOmciError(ctx, false)
1520 return
1521 }
1522 oFsm.mutexUpgradeParams.Lock()
1523 if msgObj.EntityInstance == oFsm.InactiveImageMeID {
1524 sectionNumber := msgObj.SectionNumber
1525 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
1526 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
1527
1528 oFsm.nextDownloadWindow++
1529 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
1530 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
1531 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
1532 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
1533 "expected section": oFsm.omciDownloadWindowSizeLast})
1534 oFsm.mutexUpgradeParams.Unlock()
1535 oFsm.abortOnOmciError(ctx, false)
1536 return
1537 }
1538 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
1539 //CRC computation for all data bytes of the file
1540 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
1541 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
1542 var byteSlice []byte = make([]byte, 4)
1543 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
1544 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
1545 oFsm.mutexUpgradeParams.Unlock()
1546 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvEndSwDownload)
1547 return
1548 }
1549 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
1550 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
1551 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
1552 "expected section": oFsm.omciDownloadWindowSizeLimit})
1553 oFsm.mutexUpgradeParams.Unlock()
1554 oFsm.abortOnOmciError(ctx, false)
1555 return
1556 }
1557 oFsm.nextDownloadSectionsWindow = 0
1558 oFsm.mutexUpgradeParams.Unlock()
1559 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvContinueNextWindow)
1560 return
1561 }
1562 oFsm.mutexUpgradeParams.Unlock()
1563 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1564 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1565 oFsm.abortOnOmciError(ctx, false)
1566} //handleRxSwSectionResponse
1567
1568func (oFsm *OnuUpgradeFsm) handleRxEndSwDownloadResponse(ctx context.Context, msg cmn.OmciMessage) {
1569 inAbortingState := oFsm.PAdaptFsm.PFsm.Is(UpgradeStAbortingDL)
1570
1571 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1572 if msgLayer == nil {
1573 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1574 log.Fields{"device-id": oFsm.deviceID})
1575 if !inAbortingState {
1576 oFsm.abortOnOmciError(ctx, false)
1577 } //else using error log and wait for another response or 'aborting' state timeout
1578 return
1579 }
1580 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1581 if !msgOk {
1582 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1583 log.Fields{"device-id": oFsm.deviceID})
1584 if !inAbortingState {
1585 oFsm.abortOnOmciError(ctx, false)
1586 } //else using error log and wait for another response or 'aborting' state timeout
1587 return
1588 }
1589 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1590 "device-id": oFsm.deviceID, "data-fields": msgObj})
1591 if msgObj.Result != me.Success {
1592 if msgObj.Result == me.DeviceBusy {
1593 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1594 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1595 "device-id": oFsm.deviceID})
1596 if inAbortingState {
1597 //if the EndSwDl was requested from state AbortingDL then use channel to indicate ONU busy/repeat indication
1598 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseBusy //repeat abort request
1599 }
mpagenko45586762021-10-01 08:30:22 +00001600 return
1601 }
mpagenko45586762021-10-01 08:30:22 +00001602 if inAbortingState {
1603 //if the EndSwDl was requested from state AbortingDL and response is error indication
mpagenkoa2b288f2021-10-21 11:25:27 +00001604 // that would be quite strange ONU behavior, no resolution from OnuAdapter, just let the FSM go on to disabled
1605 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - aborting anyway",
1606 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1607 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //error indication to stop waiting on EndDownloadResponse(abort)
1608 return
1609 }
1610 //else: ONU rejects the previous download, complete upgrade is immediately aborted with error
1611 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - abort upgrade",
1612 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1613 oFsm.mutexUpgradeParams.Lock()
1614 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1615 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1616 oFsm.mutexUpgradeParams.Unlock()
1617 select {
1618 case oFsm.chOnuDlReady <- false:
1619 default:
1620 }
1621 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
mpagenko45586762021-10-01 08:30:22 +00001622 return
1623 }
1624 oFsm.mutexUpgradeParams.Lock()
1625 if msgObj.EntityInstance == oFsm.InactiveImageMeID {
1626 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
mpagenko45586762021-10-01 08:30:22 +00001627 if inAbortingState {
1628 oFsm.mutexUpgradeParams.Unlock()
1629 //if the EndSwDl was requested from state AbortingDL then use channel to indicate abort acceptance
1630 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseSuccess //success
1631 return
1632 }
1633 if !oFsm.useAPIVersion43 {
1634 //in the older API version the image version check was not possible
1635 // - assume new loaded image as valid-inactive immediately
1636 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1637 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1638 oFsm.mutexUpgradeParams.Unlock()
mpagenkoa2b288f2021-10-21 11:25:27 +00001639 //use non-blocking channel (to be independent from receiver state) to indicate that the download to ONU was successful
mpagenko45586762021-10-01 08:30:22 +00001640 select {
mpagenko45586762021-10-01 08:30:22 +00001641 case oFsm.chOnuDlReady <- true:
1642 default:
1643 }
1644 } else {
1645 oFsm.mutexUpgradeParams.Unlock()
1646 }
1647 //use asynchronous channel sending to let the FSM proceed
1648 select {
1649 case oFsm.chReceiveExpectedResponse <- true:
1650 default:
1651 }
1652 return
1653 }
1654 oFsm.mutexUpgradeParams.Unlock()
1655 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: ignoring",
1656 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1657 // no state abort in case of unexpected ImageId, just keep waiting for the correct one
1658} //handleRxEndSwDownloadResponse
1659
1660func (oFsm *OnuUpgradeFsm) handleRxSwGetResponse(ctx context.Context, msg cmn.OmciMessage) {
1661 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1662 if msgLayer == nil {
1663 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1664 log.Fields{"device-id": oFsm.deviceID})
1665 oFsm.abortOnOmciError(ctx, false)
1666 return
1667 }
1668 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1669 if !msgOk {
1670 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1671 log.Fields{"device-id": oFsm.deviceID})
1672 oFsm.abortOnOmciError(ctx, false)
1673 return
1674 }
Akash Sonif80a6e62024-12-11 10:48:53 +05301675 if msgObj.EntityClass != me.SoftwareImageClassID {
1676 logger.Errorw(ctx, "Class id mismatch for software image upgrade",
1677 log.Fields{"device-id": oFsm.deviceID, "received ClassId": msgObj.EntityClass, "expected ClassId": me.SoftwareImageClassID})
1678 oFsm.abortOnOmciError(ctx, false)
1679 return
1680 }
mpagenko45586762021-10-01 08:30:22 +00001681 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1682 "device-id": oFsm.deviceID, "data-fields": msgObj})
1683 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1684 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1685 if msgObj.Result != me.Success {
1686 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1687 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1688 oFsm.abortOnOmciError(ctx, false)
1689 return
1690 }
1691 } else {
1692 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1693 log.Fields{"device-id": oFsm.deviceID})
1694 return
1695 }
mpagenko45586762021-10-01 08:30:22 +00001696 meAttributes := msgObj.Attributes
Holger Hildebrandtfdb4bba2022-03-10 12:12:59 +00001697 var imageVersion string
1698 var imageIsCommitted, imageIsActive uint8
mpagenko45586762021-10-01 08:30:22 +00001699
Holger Hildebrandtfdb4bba2022-03-10 12:12:59 +00001700 if softwareImageIsCommitted, ok := meAttributes[me.SoftwareImage_IsCommitted]; ok {
1701 if softwareImageIsActiveimage, ok := meAttributes[me.SoftwareImage_IsActive]; ok {
1702 if softwareImageVersion, ok := meAttributes[me.SoftwareImage_Version]; ok {
1703 imageIsCommitted = softwareImageIsCommitted.(uint8)
1704 imageIsActive = softwareImageIsActiveimage.(uint8)
1705 imageVersion = cmn.TrimStringFromMeOctet(softwareImageVersion)
1706 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
1707 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1708 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
1709 } else {
1710 logger.Errorw(ctx,
1711 "OnuUpgradeFsm - Not all mandatory attributes present in in SoftwareImage instance - handling stopped!",
1712 log.Fields{"device-id": oFsm.deviceID})
1713 oFsm.abortOnOmciError(ctx, false)
1714 return
1715 }
1716 }
1717 }
mpagenko45586762021-10-01 08:30:22 +00001718 if oFsm.PAdaptFsm.PFsm.Current() == UpgradeStCheckImageName {
1719 //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
1720 oFsm.verifyOnuSwStatusAfterDownload(ctx, msgObj.EntityInstance, imageVersion, imageIsActive, imageIsCommitted)
1721 return
1722 }
1723
1724 //assumed only relevant state here is upgradeStCheckCommitted
1725 oFsm.mutexUpgradeParams.Lock()
1726 oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
1727 if msgObj.EntityInstance == oFsm.InactiveImageMeID && imageIsActive == cmn.SwIsActive {
1728 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1729 // indicated in the download image version string (version must be part of the image content itself)
1730 // so checking that might be quite unreliable
1731 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1732 // in all the API references, so it can and should be checked here now
1733 if oFsm.useAPIVersion43 {
1734 if imageVersion != oFsm.imageVersion {
1735 //new active version indicated on OMCI from ONU is not the expected version
1736 logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
1737 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1738 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1739 // TODO!!!: error treatment?
1740 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1741 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1742 oFsm.mutexUpgradeParams.Unlock()
1743 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
1744 return
1745 }
1746 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1747 log.Fields{"device-id": oFsm.deviceID})
1748 }
1749 if imageIsCommitted == cmn.SwIsCommitted {
1750 oFsm.upgradePhase = cUpgradeCommitted
1751 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
1752 //store the new commit flag to onuSwImageIndications (to keep them in sync)
1753 oFsm.pDevEntry.ModifySwImageActiveCommit(ctx, imageIsCommitted)
1754 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
1755 //deviceProcStatusUpdate not used anymore,
1756 // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
1757 oFsm.mutexUpgradeParams.Unlock()
1758 //releasing the upgrade FSM on success
1759 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
1760 return
1761 }
1762 //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
1763 }
1764 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1765 oFsm.mutexUpgradeParams.Unlock()
1766 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1767 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1768 // TODO!!!: error treatment?
1769 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1770 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
1771} //handleRxSwGetResponse
1772
1773func (oFsm *OnuUpgradeFsm) verifyOnuSwStatusAfterDownload(ctx context.Context, aInstanceID uint16,
1774 aImageVersion string, aImageIsActive uint8, aImageIsCommitted uint8) {
1775 oFsm.mutexUpgradeParams.Lock()
1776 if aInstanceID == oFsm.InactiveImageMeID && aImageIsActive == cmn.SwIsInactive &&
1777 aImageIsCommitted == cmn.SwIsUncommitted {
1778 if aImageVersion != oFsm.imageVersion {
1779 //new stored inactive version indicated on OMCI from ONU is not the expected version
1780 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
1781 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID,
1782 "onu-version": aImageVersion, "expected-version": oFsm.imageVersion})
1783 //download state is set when entering the reset state
1784 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1785 oFsm.mutexUpgradeParams.Unlock()
1786 //stop the running ONU download timer
1787 //use non-blocking channel (to be independent from receiver state)
1788 select {
1789 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1790 case oFsm.chOnuDlReady <- false:
1791 default:
1792 }
1793 // TODO!!!: error treatment?
1794 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1795 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
1796 return
1797 }
1798 //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
1799 oFsm.upgradePhase = cUpgradeDownloaded
1800 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1801 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1802 //store the new inactive version to onuSwImageIndications (to keep them in sync)
1803 oFsm.pDevEntry.ModifySwImageInactiveVersion(ctx, oFsm.imageVersion)
1804 //proceed within upgrade FSM
1805 if oFsm.activateImage {
1806 //immediate activation requested
1807 oFsm.mutexUpgradeParams.Unlock()
1808 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
1809 log.Fields{"device-id": oFsm.deviceID})
1810 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvRequestActivate)
1811 } else {
1812 //have to wait on explicit activation request
1813 oFsm.mutexUpgradeParams.Unlock()
1814 logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
1815 log.Fields{"device-id": oFsm.deviceID})
1816 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvWaitForActivate)
1817 }
1818 //use non-blocking channel (to be independent from receiver state)
1819 select {
1820 //use non-blocking channel to indicate that the download to ONU was successful
1821 case oFsm.chOnuDlReady <- true:
1822 default:
1823 }
1824 return
1825 }
1826 //not the expected image/image state
1827 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1828 oFsm.mutexUpgradeParams.Unlock()
1829 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1830 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID})
1831 // TODO!!!: error treatment?
1832 //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
1833 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
1834} //verifyOnuSwStatusAfterDownload
1835
Joey Armstrong89c812c2024-01-12 19:00:20 -05001836// abortOnOmciError aborts the upgrade processing with evAbort
1837//
1838// asynchronous/synchronous based on parameter aAsync
mpagenko45586762021-10-01 08:30:22 +00001839func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool) {
mpagenko38662d02021-08-11 09:45:19 +00001840 oFsm.mutexUpgradeParams.Lock()
1841 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
mpagenko38662d02021-08-11 09:45:19 +00001842 oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
mpagenko38662d02021-08-11 09:45:19 +00001843 oFsm.mutexUpgradeParams.Unlock()
1844 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001845 if oFsm.PAdaptFsm != nil {
mpagenko38662d02021-08-11 09:45:19 +00001846 var err error
1847 if aAsync { //asynchronous call requested to ensure state transition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001848 go func(a_pAFsm *cmn.AdapterFsm) {
1849 if a_pAFsm.PFsm != nil {
1850 err = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
mpagenko38662d02021-08-11 09:45:19 +00001851 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001852 }(oFsm.PAdaptFsm)
mpagenko38662d02021-08-11 09:45:19 +00001853 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001854 if oFsm.PAdaptFsm.PFsm != nil {
1855 err = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
mpagenko38662d02021-08-11 09:45:19 +00001856 }
1857 }
1858 if err != nil {
1859 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1860 "device-id": oFsm.deviceID, "error": err})
1861 }
1862 }
1863}
1864
Joey Armstrong89c812c2024-01-12 19:00:20 -05001865// waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1866//
1867// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
mpagenko38662d02021-08-11 09:45:19 +00001868func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
1869 aWaitChannel chan bool) {
mpagenkoc26d4c02021-05-06 14:27:57 +00001870 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
mpagenko38662d02021-08-11 09:45:19 +00001871 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
mpagenkoc26d4c02021-05-06 14:27:57 +00001872 oFsm.isWaitingForAdapterDlResponse = true
1873 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001874 aSyncChannel <- struct{}{}
mpagenko80622a52021-02-09 16:53:23 +00001875 select {
1876 // maybe be also some outside cancel (but no context modeled for the moment ...)
1877 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001878 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1879 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1880 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1881 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1882 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
mpagenko39b703e2021-08-25 13:38:40 +00001883 //running into timeout here may still have the download to adapter active -> abort
1884 oFsm.pFileManager.CancelDownload(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +00001885 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1886 oFsm.isWaitingForAdapterDlResponse = false
1887 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +00001888 oFsm.mutexUpgradeParams.Lock()
mpagenko45586762021-10-01 08:30:22 +00001889 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
mpagenko39b703e2021-08-25 13:38:40 +00001890 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'DOWNLOAD_TO_ADAPTER_TIMEOUT' would be better (proto)
mpagenko39b703e2021-08-25 13:38:40 +00001891 oFsm.mutexUpgradeParams.Unlock()
1892 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001893 if oFsm.PAdaptFsm != nil && oFsm.PAdaptFsm.PFsm != nil {
1894 err := oFsm.PAdaptFsm.PFsm.Event(UpgradeEvAbort)
mpagenko39b703e2021-08-25 13:38:40 +00001895 if err != nil {
1896 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1897 "device-id": oFsm.deviceID, "error": err})
1898 }
1899 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001900 return
1901
1902 case success := <-aWaitChannel:
1903 if success {
1904 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1905 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1906 oFsm.isWaitingForAdapterDlResponse = false
1907 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1908 //let the upgrade process proceed
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001909 pUpgradeFsm := oFsm.PAdaptFsm
mpagenkoc26d4c02021-05-06 14:27:57 +00001910 if pUpgradeFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001911 _ = pUpgradeFsm.PFsm.Event(UpgradeEvPrepareSwDownload)
mpagenkoc26d4c02021-05-06 14:27:57 +00001912 } else {
1913 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1914 }
1915 return
1916 }
mpagenko39b703e2021-08-25 13:38:40 +00001917 // waiting was aborted (assumed here to be caused by
1918 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001919 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1920 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1921 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1922 oFsm.isWaitingForAdapterDlResponse = false
1923 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001924 return
mpagenko80622a52021-02-09 16:53:23 +00001925 }
1926}
mpagenkoc26d4c02021-05-06 14:27:57 +00001927
Joey Armstrong89c812c2024-01-12 19:00:20 -05001928// waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
mpagenkoc26d4c02021-05-06 14:27:57 +00001929func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1930 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1931 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1932 "duration": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001933 select {
1934 // maybe be also some outside cancel (but no context modeled for the moment ...)
1935 // case <-ctx.Done():
1936 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1937 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1938 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1939 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001940 //the upgrade process has to be aborted
mpagenko45586762021-10-01 08:30:22 +00001941 oFsm.abortOnOmciError(ctx, false)
mpagenkoc26d4c02021-05-06 14:27:57 +00001942 return
1943
1944 case success := <-aWaitChannel:
1945 if success {
1946 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001947 //all fine, let the FSM proceed like defined from the sender of this event
1948 return
1949 }
1950 // waiting was aborted (assumed here to be caused by
mpagenko39b703e2021-08-25 13:38:40 +00001951 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001952 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001953 return
1954 }
1955}
mpagenko45586762021-10-01 08:30:22 +00001956
Joey Armstrong89c812c2024-01-12 19:00:20 -05001957// waitOnAbortEndSwDlResponse waits for either abort/success or timeout of EndSwDownload (for abortion)
mpagenkoa2b288f2021-10-21 11:25:27 +00001958func (oFsm *OnuUpgradeFsm) waitOnAbortEndSwDlResponse(ctx context.Context) {
1959 logger.Debugw(ctx, "OnuUpgradeFsm start wait for EndSwDl response (abort)", log.Fields{"device-id": oFsm.deviceID})
1960 select {
1961 case <-time.After(oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second):
1962 logger.Warnw(ctx, "OnuUpgradeFsm aborting download: timeout - no response received", log.Fields{"device-id": oFsm.deviceID})
1963 pUpgradeFsm := oFsm.PAdaptFsm
1964 if pUpgradeFsm != nil {
1965 _ = pUpgradeFsm.PFsm.Event(UpgradeEvRestart)
1966 } else {
1967 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1968 }
1969 return
1970 case response := <-oFsm.chReceiveAbortEndSwDlResponse:
1971 logger.Debugw(ctx, "OnuUpgradeFsm aborting download: response received",
1972 log.Fields{"device-id": oFsm.deviceID, "response": response})
1973 pUpgradeFsm := oFsm.PAdaptFsm
1974 if pUpgradeFsm != nil {
1975 if oFsm.abortingDlEvaluateResponse(ctx, pUpgradeFsm, response) {
1976 return //event sent from function already
1977 }
1978 _ = pUpgradeFsm.PFsm.Event(UpgradeEvRestart)
1979 } else {
1980 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1981 }
1982 return
1983 } //select
1984}
1985
Joey Armstrong89c812c2024-01-12 19:00:20 -05001986// stateUpdateOnReset writes the download and/or image state on entering the reset state according to FSM internal indications
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301987//
1988//nolint:unparam
mpagenko45586762021-10-01 08:30:22 +00001989func (oFsm *OnuUpgradeFsm) stateUpdateOnReset(ctx context.Context) {
1990 oFsm.mutexUpgradeParams.Lock()
1991 defer oFsm.mutexUpgradeParams.Unlock()
1992 if !oFsm.conditionalCancelRequested {
1993 switch oFsm.upgradePhase {
1994 case cUpgradeUndefined, cUpgradeDownloading: //coming from downloading
1995 //make sure the download state is only changed in case the device has still been downloading
1996 if oFsm.volthaDownloadReason == voltha.ImageState_CANCELLED_ON_REQUEST {
1997 // indication for termination on request
1998 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
1999 } else if oFsm.volthaDownloadReason != voltha.ImageState_NO_ERROR {
2000 // indication for termination on failure
2001 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
2002 }
2003 //reset the image state from Downloading in this case
Balaji Seenivasana52fb0c2024-12-18 07:50:42 +05302004 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING_ABORTED
mpagenko45586762021-10-01 08:30:22 +00002005 //in all other upgrade phases the last set download state remains valid
2006 case cUpgradeActivating:
2007 //reset the image state from Activating in this case
2008 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATION_ABORTED
2009 case cUpgradeCommitting: // indication for request to abort waiting for response
2010 //reset the image state from Activating in this case
2011 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
2012 //default: in all other upgrade phases keep the last set imageState
2013 } //switch
2014 } else {
2015 //when reaching reset state with conditional cancel that can only result from ONU related problems
2016 // (mostly ONU down indication) - derived from resetFsms call
2017 // and it can only be related to the downloading-to-ONU phase (no need to check that additionally)
2018 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
2019 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
2020 //reset the image state from Downloading in this case
Balaji Seenivasana52fb0c2024-12-18 07:50:42 +05302021 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING_ABORTED
mpagenko45586762021-10-01 08:30:22 +00002022 }
2023}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00002024
2025// PrepareForGarbageCollection - remove references to prepare for garbage collection
2026func (oFsm *OnuUpgradeFsm) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
2027 logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})
2028 oFsm.pDeviceHandler = nil
2029 oFsm.pDownloadManager = nil
2030 oFsm.pFileManager = nil
2031 oFsm.pDevEntry = nil
2032 oFsm.pOmciCC = nil
2033}
mgouda2b946fd2025-06-16 17:54:21 +05302034
2035func (oFsm *OnuUpgradeFsm) retrySoftwareDownload(ctx context.Context) {
2036 logger.Infow(ctx, "Number of retry attempts remaining for the download window ", log.Fields{"error": oFsm.currentErrState,
2037 "device-id": oFsm.deviceID, "maxRetryAttemptsForDownloadWindow": oFsm.maxRetryAttemptsForDownloadWindow})
2038 if oFsm.maxRetryAttemptsForDownloadWindow > 0 {
2039 oFsm.maxRetryAttemptsForDownloadWindow--
2040 oFsm.nextDownloadSectionsWindow = 0 // resets the section for current window
2041
2042 // reset absolute section counter to the start of the current window
2043 oFsm.nextDownloadSectionsAbsolute = oFsm.nextDownloadWindow * uint32(oFsm.omciDownloadWindowSizeLimit+1)
2044 oFsm.mutexUpgradeParams.Unlock()
2045 _ = oFsm.PAdaptFsm.PFsm.Event(UpgradeEvContinueNextWindow)
2046 } else {
2047 oFsm.mutexUpgradeParams.Unlock()
2048 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse, max limit reached", log.Fields{"error": oFsm.currentErrState,
2049 "device-id": oFsm.deviceID})
2050 oFsm.abortOnOmciError(ctx, false)
2051 }
2052}