blob: 736e5cdd1dd93698f37cf92faa5b9ecffa31047f [file] [log] [blame]
mpagenko80622a52021-02-09 16:53:23 +00001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
mpagenkoc26d4c02021-05-06 14:27:57 +000022 "encoding/binary"
mpagenko80622a52021-02-09 16:53:23 +000023 "fmt"
24 "strconv"
mpagenkoc26d4c02021-05-06 14:27:57 +000025 "sync"
mpagenko80622a52021-02-09 16:53:23 +000026 "time"
27
28 "github.com/boguslaw-wojcik/crc32a"
29 "github.com/looplab/fsm"
30 "github.com/opencord/omci-lib-go"
31 me "github.com/opencord/omci-lib-go/generated"
Girish Gowdra50e56422021-06-01 16:46:04 -070032 "github.com/opencord/voltha-lib-go/v5/pkg/log"
mpagenko80622a52021-02-09 16:53:23 +000033 "github.com/opencord/voltha-protos/v4/go/voltha"
34)
35
36const cMaxUint32 = ^uint32(0)
37
38const (
39 // internal predefined values - some off them should later be configurable (perhaps with theses as defaults)
40 cOmciDownloadSectionSize = 31 //in bytes
41 cOmciDownloadWindowSizeLimit = 31 //in sections for window offset (windowSize(32)-1)
42 //cOmciDownloadWindowRetryMax = 2 // max attempts for a specific window
mpagenkoc26d4c02021-05-06 14:27:57 +000043 cOmciSectionInterleaveMilliseconds = 0 //DownloadSection interleave time in milliseconds (0 for no delay)
44 cOmciEndSwDlDelaySeconds = 1 //End Software Download delay after last section (may be also configurable?)
45 cWaitCountEndSwDl = 6 //maximum number of EndSwDl requests
46 cWaitDelayEndSwDlSeconds = 10 //duration, how long is waited before next request on EndSwDl
mpagenko80622a52021-02-09 16:53:23 +000047 //cOmciDownloadCompleteTimeout = 5400 //in s for the complete timeout (may be better scale to image size/ noOfWindows)
48)
49
mpagenko9c225032021-10-15 14:26:49 +000050// tEndSwDlResponseResult - Response result from EndSwDownload as used in channel indication
51type tUpgradePhase uint8
52
mpagenko80622a52021-02-09 16:53:23 +000053const (
mpagenko9c225032021-10-15 14:26:49 +000054 // undefined phase
55 cUpgradeUndefined tUpgradePhase = iota
56 // downloading image
57 cUpgradeDownloading
58 // image downloaded
59 cUpgradeDownloaded
60 // activating image
61 cUpgradeActivating
62 // image activated
63 cUpgradeActivated
64 // committing image
65 cUpgradeCommitting
66 // image committed
67 cUpgradeCommitted
68)
69
70// tEndSwDlResponseResult - Response result from EndSwDownload as used in channel indication
71type tEndSwDlResponseResult uint8
72
73const (
74 // response success
75 cEndSwDlResponseSuccess tEndSwDlResponseResult = iota
76 // response busy (repeat)
77 cEndSwDlResponseBusy
78 // response error or abort waiting for response
79 cEndSwDlResponseAbort
80)
81
82// upgrade FSM related events
83const (
mpagenko80622a52021-02-09 16:53:23 +000084 upgradeEvStart = "upgradeEvStart"
mpagenko9c225032021-10-15 14:26:49 +000085 upgradeEvDisable = "upgradeEvDisable"
mpagenkoc26d4c02021-05-06 14:27:57 +000086 upgradeEvAdapterDownload = "upgradeEvAdapterDownload"
mpagenko80622a52021-02-09 16:53:23 +000087 upgradeEvPrepareSwDownload = "upgradeEvPrepareSwDownload"
88 upgradeEvRxStartSwDownload = "upgradeEvRxStartSwDownload"
89 upgradeEvWaitWindowAck = "upgradeEvWaitWindowAck"
90 upgradeEvContinueNextWindow = "upgradeEvContinueNextWindow"
91 upgradeEvEndSwDownload = "upgradeEvEndSwDownload"
mpagenko59498c12021-03-18 14:15:15 +000092 upgradeEvWaitEndDownload = "upgradeEvWaitEndDownload"
93 upgradeEvContinueFinalize = "upgradeEvContinueFinalize"
mpagenko9c225032021-10-15 14:26:49 +000094 upgradeEvCheckImageName = "upgradeEvCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +000095 upgradeEvWaitForActivate = "upgradeEvWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000096 upgradeEvRequestActivate = "upgradeEvRequestActivate"
mpagenko183647c2021-06-08 15:25:04 +000097 upgradeEvActivationDone = "upgradeEvActivationDone"
mpagenko80622a52021-02-09 16:53:23 +000098 upgradeEvWaitForCommit = "upgradeEvWaitForCommit"
99 upgradeEvCommitSw = "upgradeEvCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +0000100 upgradeEvCheckCommitted = "upgradeEvCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +0000101
102 //upgradeEvTimeoutSimple = "upgradeEvTimeoutSimple"
103 //upgradeEvTimeoutMids = "upgradeEvTimeoutMids"
mpagenko9c225032021-10-15 14:26:49 +0000104 upgradeEvReset = "upgradeEvReset"
105 upgradeEvAbort = "upgradeEvAbort"
106 upgradeEvRestart = "upgradeEvRestart"
107 upgradeEvAbortSwDownload = "upgradeEvAbortSwDownload"
mpagenko80622a52021-02-09 16:53:23 +0000108)
109
mpagenko9c225032021-10-15 14:26:49 +0000110// upgrade FSM related states
mpagenko80622a52021-02-09 16:53:23 +0000111const (
mpagenko80622a52021-02-09 16:53:23 +0000112 upgradeStDisabled = "upgradeStDisabled"
113 upgradeStStarting = "upgradeStStarting"
mpagenkoc26d4c02021-05-06 14:27:57 +0000114 upgradeStWaitingAdapterDL = "upgradeStWaitingAdapterDL"
mpagenko80622a52021-02-09 16:53:23 +0000115 upgradeStPreparingDL = "upgradeStPreparingDL"
116 upgradeStDLSection = "upgradeStDLSection"
117 upgradeStVerifyWindow = "upgradeStVerifyWindow"
118 upgradeStFinalizeDL = "upgradeStFinalizeDL"
mpagenko59498c12021-03-18 14:15:15 +0000119 upgradeStWaitEndDL = "upgradeStWaitEndDL"
mpagenko9c225032021-10-15 14:26:49 +0000120 upgradeStCheckImageName = "upgradeStCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +0000121 upgradeStWaitForActivate = "upgradeStWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +0000122 upgradeStRequestingActivate = "upgradeStRequestingActivate"
mpagenko183647c2021-06-08 15:25:04 +0000123 upgradeStActivated = "upgradeStActivated"
mpagenko80622a52021-02-09 16:53:23 +0000124 upgradeStWaitForCommit = "upgradeStWaitForCommit"
125 upgradeStCommitSw = "upgradeStCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +0000126 upgradeStCheckCommitted = "upgradeStCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +0000127 upgradeStResetting = "upgradeStResetting"
mpagenko9c225032021-10-15 14:26:49 +0000128 upgradeStRestarting = "upgradeStRestarting"
129 upgradeStAbortingDL = "upgradeStAbortingDL"
mpagenko80622a52021-02-09 16:53:23 +0000130)
131
132//required definition for IdleState detection for activities on OMCI
133const cOnuUpgradeFsmIdleState = upgradeStWaitForCommit
134
135//OnuUpgradeFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
136type OnuUpgradeFsm struct {
137 pDeviceHandler *deviceHandler
138 pDownloadManager *adapterDownloadManager
mpagenkoc26d4c02021-05-06 14:27:57 +0000139 pFileManager *fileDownloadManager //used from R2.8 with new API version
mpagenko80622a52021-02-09 16:53:23 +0000140 deviceID string
mpagenko9c225032021-10-15 14:26:49 +0000141 pDevEntry *OnuDeviceEntry
mpagenko80622a52021-02-09 16:53:23 +0000142 pOmciCC *omciCC
143 pOnuDB *onuDeviceDB
144 requestEvent OnuDeviceEvent
145 //omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
mpagenkoc26d4c02021-05-06 14:27:57 +0000146 pAdaptFsm *AdapterFsm
147 pImageDsc *voltha.ImageDownload
148 imageBuffer []byte
149 origImageLength uint32 //as also limited by OMCI
150 imageCRC uint32 //as per OMCI - ITU I.363.5 crc
151 imageLength uint32 //including last bytes padding
152 omciDownloadWindowSizeLimit uint8 //windowSize-1 in sections
153 omciDownloadWindowSizeLast uint8 //number of sections in last window
154 noOfSections uint32 //uint32 range for sections should be sufficient for very long images
155 nextDownloadSectionsAbsolute uint32 //number of next section to download in overall image
156 nextDownloadSectionsWindow uint8 //number of next section to download within current window
157 noOfWindows uint32 //uint32 range for windows should be sufficient for very long images
158 nextDownloadWindow uint32 //number of next window to download
159 inactiveImageMeID uint16 //ME-ID of the inactive image
160 downloadToOnuTimeout4MB time.Duration //timeout for downloading the image to the ONU for a 4MB image slice
161 omciSectionInterleaveDelay time.Duration //DownloadSectionInterleave delay in milliseconds
162 delayEndSwDl bool //flag to provide a delay between last section and EndSwDl
mpagenko9c225032021-10-15 14:26:49 +0000163 repeatAbort bool //flag to indicate if OMCI EndSwDownload (abort) is to be repeated
mpagenkoc26d4c02021-05-06 14:27:57 +0000164 pLastTxMeInstance *me.ManagedEntity
165 waitCountEndSwDl uint8 //number, how often is waited for EndSwDl at maximum
166 waitDelayEndSwDl time.Duration //duration, how long is waited before next request on EndSwDl
167 chReceiveExpectedResponse chan bool
mpagenkoaa3afe92021-05-21 16:20:58 +0000168 useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
169 mutexUpgradeParams sync.RWMutex //mutex to protect members for parallel function requests and omci response processing
170 imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
171 imageIdentifier string //name of the image as used in the adapter
mpagenkoc26d4c02021-05-06 14:27:57 +0000172 mutexIsAwaitingAdapterDlResponse sync.RWMutex
173 chAdapterDlReady chan bool
174 isWaitingForAdapterDlResponse bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000175 chOnuDlReady chan bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000176 activateImage bool
177 commitImage bool
mpagenko9c225032021-10-15 14:26:49 +0000178 mutexAbortRequest sync.RWMutex
179 abortRequested voltha.ImageState_ImageFailureReason
180 conditionalCancelRequested bool
181 upgradePhase tUpgradePhase
mpagenkoaa3afe92021-05-21 16:20:58 +0000182 volthaDownloadState voltha.ImageState_ImageDownloadState
183 volthaDownloadReason voltha.ImageState_ImageFailureReason
184 volthaImageState voltha.ImageState_ImageActivationState
mpagenko9c225032021-10-15 14:26:49 +0000185 isEndSwDlOpen bool
186 chReceiveAbortEndSwDlResponse chan tEndSwDlResponseResult
mpagenko80622a52021-02-09 16:53:23 +0000187}
188
189//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
190// of ONU UNI ports via OMCI
191func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler *deviceHandler,
mpagenko15ff4a52021-03-02 10:09:20 +0000192 apDevEntry *OnuDeviceEntry, apOnuDB *onuDeviceDB,
mpagenko80622a52021-02-09 16:53:23 +0000193 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message) *OnuUpgradeFsm {
194 instFsm := &OnuUpgradeFsm{
mpagenko59498c12021-03-18 14:15:15 +0000195 pDeviceHandler: apDeviceHandler,
196 deviceID: apDeviceHandler.deviceID,
mpagenko9c225032021-10-15 14:26:49 +0000197 pDevEntry: apDevEntry,
mpagenko59498c12021-03-18 14:15:15 +0000198 pOmciCC: apDevEntry.PDevOmciCC,
199 pOnuDB: apOnuDB,
200 requestEvent: aRequestEvent,
201 omciDownloadWindowSizeLimit: cOmciDownloadWindowSizeLimit,
202 omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000203 downloadToOnuTimeout4MB: apDeviceHandler.pOpenOnuAc.dlToOnuTimeout4M,
mpagenko59498c12021-03-18 14:15:15 +0000204 waitCountEndSwDl: cWaitCountEndSwDl,
205 waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
mpagenko9c225032021-10-15 14:26:49 +0000206 upgradePhase: cUpgradeUndefined,
207 volthaDownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
mpagenkoaa3afe92021-05-21 16:20:58 +0000208 volthaDownloadReason: voltha.ImageState_NO_ERROR,
209 volthaImageState: voltha.ImageState_IMAGE_UNKNOWN,
mpagenko9c225032021-10-15 14:26:49 +0000210 abortRequested: voltha.ImageState_NO_ERROR,
mpagenko80622a52021-02-09 16:53:23 +0000211 }
mpagenko59498c12021-03-18 14:15:15 +0000212 instFsm.chReceiveExpectedResponse = make(chan bool)
mpagenkoc26d4c02021-05-06 14:27:57 +0000213 instFsm.chAdapterDlReady = make(chan bool)
214 instFsm.chOnuDlReady = make(chan bool)
mpagenko9c225032021-10-15 14:26:49 +0000215 instFsm.chReceiveAbortEndSwDlResponse = make(chan tEndSwDlResponseResult)
mpagenko80622a52021-02-09 16:53:23 +0000216
217 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
218 if instFsm.pAdaptFsm == nil {
219 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
220 "device-id": instFsm.deviceID})
221 return nil
222 }
223 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
224 upgradeStDisabled,
225 fsm.Events{
226 {Name: upgradeEvStart, Src: []string{upgradeStDisabled}, Dst: upgradeStStarting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000227 {Name: upgradeEvAdapterDownload, Src: []string{upgradeStStarting}, Dst: upgradeStWaitingAdapterDL},
228 {Name: upgradeEvPrepareSwDownload, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL}, Dst: upgradeStPreparingDL},
mpagenko80622a52021-02-09 16:53:23 +0000229 {Name: upgradeEvRxStartSwDownload, Src: []string{upgradeStPreparingDL}, Dst: upgradeStDLSection},
230 {Name: upgradeEvWaitWindowAck, Src: []string{upgradeStDLSection}, Dst: upgradeStVerifyWindow},
231 {Name: upgradeEvContinueNextWindow, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStDLSection},
232 {Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
mpagenko59498c12021-03-18 14:15:15 +0000233 {Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
234 {Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
mpagenko9c225032021-10-15 14:26:49 +0000235 //UpgradeStCheckImageName only used with useAPIVersion43
236 {Name: upgradeEvCheckImageName, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStCheckImageName},
237 //UpgradeEvWaitForActivate state transitions depend on useAPIVersion43
238 {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL, upgradeStCheckImageName}, Dst: upgradeStWaitForActivate},
239 //UpgradeEvRequestActivate state transitions depend on useAPIVersion43
240 {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStCheckImageName,
241 upgradeStWaitForActivate}, Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
mpagenko183647c2021-06-08 15:25:04 +0000242 {Name: upgradeEvActivationDone, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStActivated},
mpagenko80622a52021-02-09 16:53:23 +0000243 {Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
mpagenko1f8e8822021-06-25 14:10:21 +0000244 {Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
245 upgradeStActivated}, Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
mpagenko15ff4a52021-03-02 10:09:20 +0000246 {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000247
248 /*
249 {Name: upgradeEvTimeoutSimple, Src: []string{
250 upgradeStCreatingDot1PMapper, upgradeStCreatingMBPCD, upgradeStSettingTconts, upgradeStSettingDot1PMapper}, Dst: upgradeStStarting},
251 {Name: upgradeEvTimeoutMids, Src: []string{
252 upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
253 */
254 // exceptional treatments
mpagenko1f8e8822021-06-25 14:10:21 +0000255 //on upgradeEvReset: upgradeStRequestingActivate, upgradeStWaitForCommit and upgradeStActivated are not reset
256 // (to let the FSM survive the expected OnuDown indication)
mpagenkoc26d4c02021-05-06 14:27:57 +0000257 {Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko9c225032021-10-15 14:26:49 +0000258 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
259 upgradeStWaitForActivate,
260 upgradeStCommitSw, upgradeStCheckCommitted, upgradeStAbortingDL},
mpagenko80622a52021-02-09 16:53:23 +0000261 Dst: upgradeStResetting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000262 {Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko9c225032021-10-15 14:26:49 +0000263 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
264 upgradeStWaitForActivate,
265 upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit,
266 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000267 Dst: upgradeStResetting},
mpagenko9c225032021-10-15 14:26:49 +0000268 {Name: upgradeEvAbortSwDownload, Src: []string{upgradeStResetting}, Dst: upgradeStAbortingDL},
269 {Name: upgradeEvRestart, Src: []string{upgradeStResetting, upgradeStAbortingDL}, Dst: upgradeStRestarting},
270 {Name: upgradeEvDisable, Src: []string{upgradeStRestarting}, Dst: upgradeStDisabled},
mpagenko80622a52021-02-09 16:53:23 +0000271 },
272 fsm.Callbacks{
273 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
274 "enter_" + upgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
mpagenkoc26d4c02021-05-06 14:27:57 +0000275 "enter_" + upgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000276 "enter_" + upgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
277 "enter_" + upgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
278 "enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
279 "enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
mpagenko59498c12021-03-18 14:15:15 +0000280 "enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
mpagenko9c225032021-10-15 14:26:49 +0000281 "enter_" + upgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000282 "enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
283 "enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
mpagenko15ff4a52021-03-02 10:09:20 +0000284 "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000285 "enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
mpagenko9c225032021-10-15 14:26:49 +0000286 "enter_" + upgradeStAbortingDL: func(e *fsm.Event) { instFsm.enterAbortingDL(ctx, e) },
287 "enter_" + upgradeStRestarting: func(e *fsm.Event) { instFsm.enterRestarting(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000288 "enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
289 },
290 )
291 if instFsm.pAdaptFsm.pFsm == nil {
292 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
293 "device-id": instFsm.deviceID})
294 return nil
295 }
296
297 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
298 return instFsm
299}
300
301//SetDownloadParams configures the needed parameters for a specific download to the ONU
mpagenkoc26d4c02021-05-06 14:27:57 +0000302// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000303func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
304 apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
mpagenko80622a52021-02-09 16:53:23 +0000305 pBaseFsm := oFsm.pAdaptFsm.pFsm
306 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000307 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000308 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
309 "device-id": oFsm.deviceID, "image-description": apImageDsc})
mpagenko15ff4a52021-03-02 10:09:20 +0000310 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000311 oFsm.pImageDsc = apImageDsc
312 oFsm.pDownloadManager = apDownloadManager
Holger Hildebrandtac1e0592021-06-03 15:16:49 +0000313 oFsm.activateImage = true
314 oFsm.commitImage = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000315 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000316
317 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000318 // let the upgrade FSM proceed to PreparingDL
mpagenko80622a52021-02-09 16:53:23 +0000319 _ = aPBaseFsm.Event(upgradeEvPrepareSwDownload)
320 }(pBaseFsm)
321 return nil
322 }
323 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
324 "device-id": oFsm.deviceID})
325 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
326}
327
mpagenkoc26d4c02021-05-06 14:27:57 +0000328//SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
329// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
330// called from 'new' API Download_onu_image
331func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
332 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *fileDownloadManager,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000333 aImageIdentifier string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000334 oFsm.mutexUpgradeParams.Lock()
335 var pBaseFsm *fsm.FSM = nil
336 if oFsm.pAdaptFsm != nil {
337 pBaseFsm = oFsm.pAdaptFsm.pFsm
338 }
339 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
340 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
341 "device-id": oFsm.deviceID, "image-description": apImageRequest})
342 oFsm.useAPIVersion43 = true
343 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
344 oFsm.pFileManager = apDownloadManager
345 oFsm.imageIdentifier = aImageIdentifier
346 oFsm.imageVersion = apImageRequest.Image.Version
347 oFsm.activateImage = apImageRequest.ActivateOnSuccess
348 oFsm.commitImage = apImageRequest.CommitOnSuccess
mpagenko9c225032021-10-15 14:26:49 +0000349 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //state change indication for download request
mpagenkoc26d4c02021-05-06 14:27:57 +0000350 oFsm.mutexUpgradeParams.Unlock()
351 _ = pBaseFsm.Event(upgradeEvAdapterDownload) //no need to call the FSM event in background here
352 return nil
353 }
354 oFsm.mutexUpgradeParams.Unlock()
355 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
356 "device-id": oFsm.deviceID})
357 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
358}
359
360//SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
361// called from 'new' API Activate_onu_image
362func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
363 aImageIdentifier string, aCommit bool) error {
mpagenko9c225032021-10-15 14:26:49 +0000364 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
365 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
mpagenkoc26d4c02021-05-06 14:27:57 +0000366 oFsm.mutexUpgradeParams.Lock()
367 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
368 // (as long as the Imageidentifier is correct)
mpagenkoc26d4c02021-05-06 14:27:57 +0000369 if aImageIdentifier != oFsm.imageIdentifier {
370 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
371 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
372 oFsm.mutexUpgradeParams.Unlock()
373 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
374 oFsm.deviceID))
375 }
376 oFsm.activateImage = true
377 oFsm.commitImage = aCommit
378 oFsm.mutexUpgradeParams.Unlock()
379 var pBaseFsm *fsm.FSM = nil
380 if oFsm.pAdaptFsm != nil {
381 pBaseFsm = oFsm.pAdaptFsm.pFsm
382 }
383 if pBaseFsm != nil {
384 if pBaseFsm.Is(upgradeStWaitForActivate) {
385 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
386 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenko9c225032021-10-15 14:26:49 +0000387 } else {
388 logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
389 "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000390 }
391 return nil
392 }
393 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
394 "device-id": oFsm.deviceID})
395 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
396}
397
398//SetActivationParamsStart starts upgrade processing with immediate activation
399// called from 'new' API Activate_onu_image
400func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
401 oFsm.mutexUpgradeParams.Lock()
402 var pBaseFsm *fsm.FSM = nil
403 if oFsm.pAdaptFsm != nil {
404 pBaseFsm = oFsm.pAdaptFsm.pFsm
405 }
406 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
407 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
408 "device-id": oFsm.deviceID, "image-version": aImageVersion})
409 oFsm.useAPIVersion43 = true
410 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
411 oFsm.imageVersion = aImageVersion
412 oFsm.activateImage = true
413 oFsm.commitImage = aCommit
mpagenko9c225032021-10-15 14:26:49 +0000414 // indicate start of the upgrade activity
415 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000416 oFsm.mutexUpgradeParams.Unlock()
417 //directly request the FSM to activate the image
418 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
419 return nil
420 }
421 oFsm.mutexUpgradeParams.Unlock()
422 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
423 "device-id": oFsm.deviceID})
424 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
425}
426
427//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
428// called from 'new' API Commit_onu_image
mpagenko9c225032021-10-15 14:26:49 +0000429func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
430 aImageIdentifier string, aImageVersion string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000431 oFsm.mutexUpgradeParams.Lock()
432 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
433 // (as long as the Imageidentifier is correct)
434 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
mpagenko9c225032021-10-15 14:26:49 +0000435 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "image-version": aImageVersion})
436 if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000437 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
mpagenko9c225032021-10-15 14:26:49 +0000438 "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
439 "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
mpagenkoc26d4c02021-05-06 14:27:57 +0000440 oFsm.mutexUpgradeParams.Unlock()
441 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
442 oFsm.deviceID))
443 }
444 oFsm.commitImage = true
445 oFsm.mutexUpgradeParams.Unlock()
446 var pBaseFsm *fsm.FSM = nil
447 if oFsm.pAdaptFsm != nil {
448 pBaseFsm = oFsm.pAdaptFsm.pFsm
449 }
450 if pBaseFsm != nil {
mpagenko183647c2021-06-08 15:25:04 +0000451 //let the FSM decide if it is ready to process the event
452 logger.Debugw(ctx, "OnuUpgradeFsm requesting commit",
453 log.Fields{"device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
454 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000455 return nil
456 }
mpagenko9c225032021-10-15 14:26:49 +0000457 //should never occur
mpagenkoc26d4c02021-05-06 14:27:57 +0000458 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
459 "device-id": oFsm.deviceID})
460 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
461}
462
463//SetCommitmentParamsStart starts upgrade processing with immediate commitment
464// called from 'new' API Commit_onu_image
465func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
466 oFsm.mutexUpgradeParams.Lock()
467 var pBaseFsm *fsm.FSM = nil
468 if oFsm.pAdaptFsm != nil {
469 pBaseFsm = oFsm.pAdaptFsm.pFsm
470 }
471 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
472 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
473 "device-id": oFsm.deviceID, "image-version": aImageVersion})
474 oFsm.useAPIVersion43 = true
475 oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
476 oFsm.imageVersion = aImageVersion
477 oFsm.commitImage = true
mpagenko9c225032021-10-15 14:26:49 +0000478 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING //state change indication for activate request
mpagenkoc26d4c02021-05-06 14:27:57 +0000479 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000480 //directly request the FSM to commit the image
mpagenkoc26d4c02021-05-06 14:27:57 +0000481 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
482 return nil
483 }
484 oFsm.mutexUpgradeParams.Unlock()
485 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
486 "device-id": oFsm.deviceID})
487 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
488}
489
mpagenko1f8e8822021-06-25 14:10:21 +0000490//GetCommitFlag delivers the commit flag that was configured here
491func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
492 oFsm.mutexUpgradeParams.RLock()
493 defer oFsm.mutexUpgradeParams.RUnlock()
494 return oFsm.commitImage
495}
496
mpagenko9c225032021-10-15 14:26:49 +0000497//GetImageStates delivers the download/image states as per device protobuf or error indication
mpagenkoaa3afe92021-05-21 16:20:58 +0000498func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
mpagenko9c225032021-10-15 14:26:49 +0000499 aImageIdentifier string, aVersion string) *voltha.ImageState {
mpagenkoaa3afe92021-05-21 16:20:58 +0000500 pImageState := &voltha.ImageState{}
mpagenko9c225032021-10-15 14:26:49 +0000501 pImageState.Version = aVersion //version as requested
mpagenkoaa3afe92021-05-21 16:20:58 +0000502 // check if the request refers to some active image/version of the processing
503 oFsm.mutexUpgradeParams.RLock()
504 if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
505 pImageState.DownloadState = oFsm.volthaDownloadState
506 pImageState.Reason = oFsm.volthaDownloadReason
507 pImageState.ImageState = oFsm.volthaImageState
508 } else {
509 pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
510 pImageState.Reason = voltha.ImageState_NO_ERROR
511 pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
512 }
513 oFsm.mutexUpgradeParams.RUnlock()
mpagenko9c225032021-10-15 14:26:49 +0000514 return pImageState
mpagenkoaa3afe92021-05-21 16:20:58 +0000515}
516
mpagenko9c225032021-10-15 14:26:49 +0000517//SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
518func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
mpagenko183647c2021-06-08 15:25:04 +0000519 oFsm.mutexUpgradeParams.Lock()
520 defer oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000521 oFsm.upgradePhase = cUpgradeActivated
522 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
mpagenko183647c2021-06-08 15:25:04 +0000523}
524
mpagenkoc26d4c02021-05-06 14:27:57 +0000525//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko9c225032021-10-15 14:26:49 +0000526func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
527 aReason voltha.ImageState_ImageFailureReason) {
528 pAdaptFsm := oFsm.pAdaptFsm
529 if pAdaptFsm == nil || pAdaptFsm.pFsm == nil {
530 logger.Warnw(ctx, "OnuUpgradeFsm cancel, but FSM invalid", log.Fields{
531 "device-id": oFsm.deviceID})
532 return
533 }
534 logger.Debugw(ctx, "OnuUpgradeFsm start canceling", log.Fields{
535 "device-id": oFsm.deviceID, "in fsm-state": pAdaptFsm.pFsm.Current()})
536 oFsm.mutexAbortRequest.Lock()
537 oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
538 oFsm.mutexAbortRequest.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000539 //mutex protection is required for possible concurrent access to FSM members
540 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
541 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
542 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
543 if oFsm.isWaitingForAdapterDlResponse {
544 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
545 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
546 oFsm.chAdapterDlReady <- false
547 } else {
548 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
549 }
550 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
551
552 // 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 +0000553 // specific here: See definition of state changes: some states are excluded from reset for possible later commit
mpagenko9c225032021-10-15 14:26:49 +0000554 pAdaptFsm = oFsm.pAdaptFsm
555 if pAdaptFsm != nil && pAdaptFsm.pFsm != nil {
mpagenkoc26d4c02021-05-06 14:27:57 +0000556 // calling FSM events in background to avoid blocking of the caller
mpagenko9c225032021-10-15 14:26:49 +0000557 go func(apFsm *fsm.FSM) {
558 if apFsm.Is(upgradeStWaitEndDL) {
559 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
560 } else if apFsm.Is(upgradeStAbortingDL) {
561 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //abort waiting on EndDownloadResponse
562 }
563
564 var err error
565 if abCompleteAbort {
566 // in case of unconditional abort request the ImageState is set immediately
567 oFsm.mutexUpgradeParams.Lock()
568 //any previous lingering conditional cancelRequest is superseded by this abortion
569 oFsm.conditionalCancelRequested = false
570 oFsm.volthaDownloadReason = aReason
571 oFsm.mutexUpgradeParams.Unlock()
572 err = apFsm.Event(upgradeEvAbort) //as unconditional default FSM cancellation
573 } else {
574 //at conditional abort request the image states are set when reaching the reset state
575 oFsm.mutexUpgradeParams.Lock()
576 oFsm.conditionalCancelRequested = true
577 oFsm.mutexUpgradeParams.Unlock()
578 err = apFsm.Event(upgradeEvReset) //as state-conditional default FSM cleanup
579 }
580 if err != nil {
581 //error return is expected in case of conditional request and no state transition
582 logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
583 "device-id": oFsm.deviceID, "error": err})
584 }
585 logger.Debugw(ctx, "OnuUpgradeFsm canceling done", log.Fields{
586 "device-id": oFsm.deviceID})
587 }(pAdaptFsm.pFsm)
588 } else { //the FSM seems already to be in some released state
589 logger.Warnw(ctx, "OnuUpgradeFsm canceling without FSM event", log.Fields{
590 "device-id": oFsm.deviceID, "in fsm-state": pAdaptFsm.pFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000591 }
592}
593
mpagenko80622a52021-02-09 16:53:23 +0000594func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
595 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
596 "device-id": oFsm.deviceID})
597
598 // start go routine for processing of LockState messages
599 go oFsm.processOmciUpgradeMessages(ctx)
600}
601
mpagenkoc26d4c02021-05-06 14:27:57 +0000602//enterWaitingAdapterDL state can only be reached with useAPIVersion43
603func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
604 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
605 "device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +0000606 syncChannel := make(chan struct{})
607 go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
608 //block until the wait routine is really blocked on chAdapterDlReady
609 <-syncChannel
mpagenkoc26d4c02021-05-06 14:27:57 +0000610 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
611}
612
mpagenko80622a52021-02-09 16:53:23 +0000613func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
614 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
615 "device-id": oFsm.deviceID})
616
mpagenkoc26d4c02021-05-06 14:27:57 +0000617 var fileLen int64
618 var err error
mpagenkoaa3afe92021-05-21 16:20:58 +0000619 oFsm.mutexUpgradeParams.Lock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000620 if oFsm.useAPIVersion43 {
621 //with the new API structure download to adapter is implicit and we have to wait until the image is available
622 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
623 } else {
624 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
625 }
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000626 if err != nil || fileLen == 0 || fileLen > int64(cMaxUint32) {
mpagenko9c225032021-10-15 14:26:49 +0000627 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000628 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000629 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
630 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
631 pBaseFsm := oFsm.pAdaptFsm
632 // Can't call FSM Event directly, decoupling it
633 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000634 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000635 }(pBaseFsm)
636 return
637 }
638
mpagenkoc26d4c02021-05-06 14:27:57 +0000639 //copy file content to buffer
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000640 var imageBuffer []byte
mpagenkoc26d4c02021-05-06 14:27:57 +0000641 if oFsm.useAPIVersion43 {
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000642 imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +0000643 } else {
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000644 imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
mpagenkoc26d4c02021-05-06 14:27:57 +0000645 }
mpagenko80622a52021-02-09 16:53:23 +0000646 if err != nil {
mpagenko9c225032021-10-15 14:26:49 +0000647 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000648 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000649 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
650 "device-id": oFsm.deviceID, "error": err})
651 pBaseFsm := oFsm.pAdaptFsm
652 // Can't call FSM Event directly, decoupling it
653 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000654 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000655 }(pBaseFsm)
656 return
657 }
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000658 //provide slice capacity already with the reserve of one section to avoid inflation of the slice to double size at append
659 oFsm.imageBuffer = make([]byte, fileLen, fileLen+cOmciDownloadSectionSize)
660 //better use a copy of the read image buffer in case the buffer/file is modified from outside,
661 // this also limits the slice len to the expected maximum fileLen
662 copy(oFsm.imageBuffer, imageBuffer)
mpagenko80622a52021-02-09 16:53:23 +0000663
664 oFsm.noOfSections = uint32(fileLen / cOmciDownloadSectionSize)
665 if fileLen%cOmciDownloadSectionSize > 0 {
mpagenkoc26d4c02021-05-06 14:27:57 +0000666 bufferPadding := make([]byte, cOmciDownloadSectionSize-uint32((fileLen)%cOmciDownloadSectionSize))
mpagenko80622a52021-02-09 16:53:23 +0000667 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
Holger Hildebrandt33f701d2021-12-22 10:07:58 +0000668 oFsm.imageBuffer = append(oFsm.imageBuffer, bufferPadding...)
mpagenko80622a52021-02-09 16:53:23 +0000669 oFsm.noOfSections++
670 }
671 oFsm.origImageLength = uint32(fileLen)
672 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000673 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
674 "MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
675 "ImageSize": oFsm.imageLength, "original file size": fileLen})
676 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
mpagenkoaa3afe92021-05-21 16:20:58 +0000677
678 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000679
680 // flush commMetricsChan
681 select {
682 case <-oFsm.chOnuDlReady:
683 logger.Debug(ctx, "flushed OnuDlReady channel")
684 default:
685 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000686 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
687
mpagenko9c225032021-10-15 14:26:49 +0000688 err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000689 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
690 if err != nil {
691 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
692 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000693 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000694 return
695 }
mpagenko9c225032021-10-15 14:26:49 +0000696 oFsm.isEndSwDlOpen = true
mpagenko80622a52021-02-09 16:53:23 +0000697}
698
699func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
700 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
701 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
mpagenko9c225032021-10-15 14:26:49 +0000702 //use a background routine to send the multiple download sections frames in a loop
703 // in order to avoid blocking on synchrounous event calls for the entire (long) processing time
704 go oFsm.runSwDlSectionWindow(ctx)
705}
mpagenko80622a52021-02-09 16:53:23 +0000706
mpagenko9c225032021-10-15 14:26:49 +0000707//runSwDlSectionWindow runs a loop to send all DlSection frames of one window in background
708// may be aborted by parallel change of abortRequested
709func (oFsm *OnuUpgradeFsm) runSwDlSectionWindow(ctx context.Context) {
mpagenko80622a52021-02-09 16:53:23 +0000710 var windowAckRequest uint8 = 0
711 var bufferStartOffset uint32
712 var bufferEndOffset uint32
713 var downloadSection []byte
714 framePrint := false //default no printing of downloadSection frames
mpagenkoaa3afe92021-05-21 16:20:58 +0000715 oFsm.mutexUpgradeParams.Lock()
mpagenko9c225032021-10-15 14:26:49 +0000716 oFsm.upgradePhase = cUpgradeDownloading //start of downloading image to ONU
mpagenko80622a52021-02-09 16:53:23 +0000717 if oFsm.nextDownloadSectionsAbsolute == 0 {
718 //debug print of first section frame
719 framePrint = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000720 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
mpagenko80622a52021-02-09 16:53:23 +0000721 }
mpagenko80622a52021-02-09 16:53:23 +0000722 for {
mpagenko9c225032021-10-15 14:26:49 +0000723 oFsm.mutexAbortRequest.RLock()
724 // this way out of the section download loop on abort request
725 if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
726 //states are updated when entering the reset state ...
727 oFsm.volthaDownloadReason = oFsm.abortRequested
728 oFsm.mutexAbortRequest.RUnlock()
729 oFsm.mutexUpgradeParams.Unlock()
730 pUpgradeFsm := oFsm.pAdaptFsm
731 if pUpgradeFsm != nil {
732 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
733 logger.Debugw(ctx, "aborting runSwDlSectionWindow", log.Fields{
734 "device-id": oFsm.deviceID, "reason": oFsm.volthaDownloadReason})
735 return
736 }
737 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
738 return
739 }
740 oFsm.mutexAbortRequest.RUnlock()
741
mpagenko80622a52021-02-09 16:53:23 +0000742 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
743 bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
744 logger.Debugw(ctx, "DlSection values are", log.Fields{
745 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
746 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
747 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
748 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
749 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
750 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
751 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
mpagenko9c225032021-10-15 14:26:49 +0000752 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000753 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000754 //logical error -- reset the FSM
mpagenko9c225032021-10-15 14:26:49 +0000755 pUpgradeFsm := oFsm.pAdaptFsm
756 if pUpgradeFsm != nil {
757 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
758 return
759 }
760 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000761 return
762 }
763 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
764 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
765 windowAckRequest = 1
766 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
767 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
768 }
769 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
770 windowAckRequest = 1
771 framePrint = true //debug print of last frame
mpagenko15ff4a52021-03-02 10:09:20 +0000772 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
773 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000774 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
775 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000776 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko9c225032021-10-15 14:26:49 +0000777 err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000778 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
779 if err != nil {
780 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000781 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000782 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +0000783 return
784 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000785 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000786 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
787 if windowAckRequest == 1 {
mpagenkoaa3afe92021-05-21 16:20:58 +0000788 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000789 pUpgradeFsm := oFsm.pAdaptFsm
790 if pUpgradeFsm != nil {
791 _ = pUpgradeFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
792 return
793 }
794 logger.Warnw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000795 return
796 }
797 framePrint = false //for the next Section frame (if wanted, can be enabled in logic before sendXXX())
798 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000799 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000800 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenkoaa3afe92021-05-21 16:20:58 +0000801 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko59498c12021-03-18 14:15:15 +0000802 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenkoaa3afe92021-05-21 16:20:58 +0000803 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000804 }
805 }
mpagenko9c225032021-10-15 14:26:49 +0000806} //runSwDlSectionWindow
mpagenko80622a52021-02-09 16:53:23 +0000807
808func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
809 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
810 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
811}
812
813func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000814 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000815 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
mpagenko80622a52021-02-09 16:53:23 +0000816
mpagenkoaa3afe92021-05-21 16:20:58 +0000817 oFsm.mutexUpgradeParams.RLock()
mpagenko80622a52021-02-09 16:53:23 +0000818 if oFsm.delayEndSwDl {
mpagenkoaa3afe92021-05-21 16:20:58 +0000819 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000820 //give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
821 // should not be set in case this state is used for real download abort (not yet implemented)
822 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoaa3afe92021-05-21 16:20:58 +0000823 } else {
824 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000825 }
826
mpagenko59498c12021-03-18 14:15:15 +0000827 pBaseFsm := oFsm.pAdaptFsm
828 if pBaseFsm == nil {
mpagenko9c225032021-10-15 14:26:49 +0000829 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
830 oFsm.mutexUpgradeParams.Lock()
831 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
832 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000833 // Can't call FSM Event directly, decoupling it
834 go func(a_pAFsm *AdapterFsm) {
835 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
836 }(pBaseFsm)
837 return
838 }
mpagenko9c225032021-10-15 14:26:49 +0000839 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko59498c12021-03-18 14:15:15 +0000840 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.origImageLength, oFsm.imageCRC)
mpagenko80622a52021-02-09 16:53:23 +0000841 if err != nil {
mpagenko9c225032021-10-15 14:26:49 +0000842 logger.Errorw(ctx, "EndSwDl abort: error sending EndSwDl", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000843 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000844 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000845 return
846 }
mpagenko59498c12021-03-18 14:15:15 +0000847 // go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
848 // Can't call FSM Event directly, decoupling it
849 go func(a_pAFsm *AdapterFsm) {
850 _ = a_pAFsm.pFsm.Event(upgradeEvWaitEndDownload)
851 }(pBaseFsm)
852}
853
854func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
855 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
856 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
857 if oFsm.waitCountEndSwDl == 0 {
858 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
859 "device-id": oFsm.deviceID})
860 pBaseFsm := oFsm.pAdaptFsm
861 if pBaseFsm == nil {
862 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
863 "device-id": oFsm.deviceID})
864 return
865 }
mpagenko9c225032021-10-15 14:26:49 +0000866 oFsm.mutexUpgradeParams.Lock()
867 oFsm.isEndSwDlOpen = false //no need to additionally request abort of download (already finished)
868 oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
869 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000870 go func(a_pAFsm *AdapterFsm) {
871 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
872 }(pBaseFsm)
873 return
874 }
875
876 oFsm.waitCountEndSwDl--
877 select {
878 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
879 pBaseFsm := oFsm.pAdaptFsm
880 if pBaseFsm == nil {
881 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
882 "device-id": oFsm.deviceID})
883 //FSM may be reset already from somewhere else, nothing we can do here anymore
884 return
885 }
886 //retry End SW DL
mpagenkoaa3afe92021-05-21 16:20:58 +0000887 oFsm.mutexUpgradeParams.Lock()
mpagenko59498c12021-03-18 14:15:15 +0000888 oFsm.delayEndSwDl = false //no more extra delay for the request
mpagenkoaa3afe92021-05-21 16:20:58 +0000889 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000890 go func(a_pAFsm *AdapterFsm) {
891 _ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
892 }(pBaseFsm)
893 return
894 case success := <-oFsm.chReceiveExpectedResponse:
895 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +0000896 oFsm.isEndSwDlOpen = false //no request to abort of download (already finished or immediate abort)
mpagenko59498c12021-03-18 14:15:15 +0000897 pBaseFsm := oFsm.pAdaptFsm
898 if pBaseFsm == nil {
899 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
900 "device-id": oFsm.deviceID})
901 //FSM may be reset already from somewhere else, nothing we can do here anymore
902 return
903 }
904 if success {
905 //answer received with ready indication
mpagenko9c225032021-10-15 14:26:49 +0000906 //useAPIVersion43 may not conflict in concurrency in this state function
907 if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
mpagenkoc26d4c02021-05-06 14:27:57 +0000908 go func(a_pAFsm *AdapterFsm) {
mpagenko9c225032021-10-15 14:26:49 +0000909 _ = a_pAFsm.pFsm.Event(upgradeEvCheckImageName)
mpagenkoc26d4c02021-05-06 14:27:57 +0000910 }(pBaseFsm)
mpagenko9c225032021-10-15 14:26:49 +0000911 } else { // elder API usage does not support image version check -immediately consider download as successful
912 if oFsm.activateImage {
913 //immediate activation requested
914 go func(a_pAFsm *AdapterFsm) {
915 _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
916 }(pBaseFsm)
917 } else {
918 //have to wait on explicit activation request
919 go func(a_pAFsm *AdapterFsm) {
920 _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
921 }(pBaseFsm)
922 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000923 }
mpagenko59498c12021-03-18 14:15:15 +0000924 return
925 }
926 //timer was aborted
mpagenko9c225032021-10-15 14:26:49 +0000927 oFsm.abortOnOmciError(ctx, true)
mpagenko59498c12021-03-18 14:15:15 +0000928 return
929 }
mpagenko80622a52021-02-09 16:53:23 +0000930}
931
mpagenko9c225032021-10-15 14:26:49 +0000932func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
933 logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
934 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
935 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
936 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
937 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
938 false, oFsm.pAdaptFsm.commChan)
939 if err != nil {
940 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
941 log.Fields{"device-id": oFsm.deviceID, "Error": err})
942 oFsm.abortOnOmciError(ctx, true)
943 return
944 }
945 oFsm.pLastTxMeInstance = meInstance
946}
947
mpagenko80622a52021-02-09 16:53:23 +0000948func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
949 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
950 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
951
mpagenkoaa3afe92021-05-21 16:20:58 +0000952 oFsm.mutexUpgradeParams.Lock()
953 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
954 oFsm.mutexUpgradeParams.Unlock()
955
mpagenko9c225032021-10-15 14:26:49 +0000956 err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000957 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
958 if err != nil {
959 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
960 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000961 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +0000962 return
963 }
mpagenko9c225032021-10-15 14:26:49 +0000964 oFsm.mutexUpgradeParams.Lock()
965 oFsm.upgradePhase = cUpgradeActivating //start of image activation for ONU
966 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
967 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000968}
969
970func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko9c225032021-10-15 14:26:49 +0000971 logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
972 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
973 //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
974 // (which is a bit problematic as the ONU might already be in committed state,
975 // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
976 if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
mpagenkoaa3afe92021-05-21 16:20:58 +0000977 oFsm.mutexUpgradeParams.Lock()
mpagenko9c225032021-10-15 14:26:49 +0000978 if activeImageID == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +0000979 inactiveImageID := oFsm.inactiveImageMeID
mpagenko15ff4a52021-03-02 10:09:20 +0000980 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
mpagenkoaa3afe92021-05-21 16:20:58 +0000981 "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
982 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
mpagenko9c225032021-10-15 14:26:49 +0000983 oFsm.upgradePhase = cUpgradeCommitting //start of image commitment for ONU
mpagenkoaa3afe92021-05-21 16:20:58 +0000984 oFsm.mutexUpgradeParams.Unlock()
mpagenko9c225032021-10-15 14:26:49 +0000985 err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenkoaa3afe92021-05-21 16:20:58 +0000986 oFsm.pAdaptFsm.commChan, inactiveImageID) //more efficient activeImageID with above check
mpagenko15ff4a52021-03-02 10:09:20 +0000987 if err != nil {
988 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
989 "device-id": oFsm.deviceID, "error": err})
mpagenko9c225032021-10-15 14:26:49 +0000990 oFsm.abortOnOmciError(ctx, true)
mpagenko15ff4a52021-03-02 10:09:20 +0000991 return
992 }
993 return
994 }
mpagenko9c225032021-10-15 14:26:49 +0000995 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000996 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
997 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
mpagenko9c225032021-10-15 14:26:49 +0000998 } else {
999 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
1000 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +00001001 }
mpagenko9c225032021-10-15 14:26:49 +00001002 oFsm.mutexUpgradeParams.Lock()
1003 oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
1004 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1005 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001006 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1007 pBaseFsm := oFsm.pAdaptFsm
1008 // Can't call FSM Event directly, decoupling it
1009 go func(a_pAFsm *AdapterFsm) {
1010 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
1011 }(pBaseFsm)
1012}
1013
1014func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
mpagenko9c225032021-10-15 14:26:49 +00001015 logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +00001016 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
mpagenko15ff4a52021-03-02 10:09:20 +00001017 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
mpagenko9c225032021-10-15 14:26:49 +00001018 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra0b235842021-03-09 13:06:46 -08001019 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
mpagenko15ff4a52021-03-02 10:09:20 +00001020 //accept also nil as (error) return value for writing to LastTx
1021 // - this avoids misinterpretation of new received OMCI messages
ozgecanetsiab36ed572021-04-01 10:38:48 +03001022 if err != nil {
1023 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
1024 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko9c225032021-10-15 14:26:49 +00001025 oFsm.abortOnOmciError(ctx, true)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001026 return
1027 }
mpagenko15ff4a52021-03-02 10:09:20 +00001028 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +00001029}
1030
1031func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1032 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
1033
mpagenko9c225032021-10-15 14:26:49 +00001034 oFsm.stateUpdateOnReset(ctx)
1035
1036 oFsm.mutexAbortRequest.Lock()
1037 //to be sure to abort a possibly still running runSwDlSectionWindow()
1038 // in case the reset was not received from cancel() and download not finished correctly
1039 oFsm.abortRequested = oFsm.volthaDownloadReason
1040 oFsm.mutexAbortRequest.Unlock()
1041
mpagenkoc26d4c02021-05-06 14:27:57 +00001042 // in case the download-to-ONU timer is still running - cancel it
mpagenko9c225032021-10-15 14:26:49 +00001043 //use non-blocking channel (to be independent from receiver state)
1044 select {
1045 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1046 case oFsm.chOnuDlReady <- false:
1047 default:
1048 }
1049 pConfigUpgradeStateAFsm := oFsm.pAdaptFsm
1050 if pConfigUpgradeStateAFsm != nil {
1051 var nextEvent string
1052 if oFsm.isEndSwDlOpen {
1053 if oFsm.repeatAbort {
1054 oFsm.delayEndSwDl = true //run next abort with delay
1055 } else { //initial request
1056 oFsm.delayEndSwDl = false //run next abort with no delay
1057 oFsm.waitCountEndSwDl = cWaitCountEndSwDl //init for possible repetitions
1058 }
1059 nextEvent = upgradeEvAbortSwDownload
1060 } else {
1061 nextEvent = upgradeEvRestart
1062 }
1063 // Can't call FSM Event directly, decoupling it
1064 go func(a_pAFsm *AdapterFsm) {
1065 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1066 _ = a_pAFsm.pFsm.Event(nextEvent)
1067 }
1068 }(pConfigUpgradeStateAFsm)
1069 }
1070}
1071
1072func (oFsm *OnuUpgradeFsm) enterAbortingDL(ctx context.Context, e *fsm.Event) {
1073 logger.Debugw(ctx, "OnuUpgradeFsm aborting download to ONU", log.Fields{"device-id": oFsm.deviceID})
1074
1075 oFsm.mutexUpgradeParams.RLock()
1076 if oFsm.delayEndSwDl {
1077 oFsm.mutexUpgradeParams.RUnlock()
1078 //give the ONU some time for image discard activities
1079 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoc26d4c02021-05-06 14:27:57 +00001080 } else {
mpagenko9c225032021-10-15 14:26:49 +00001081 oFsm.mutexUpgradeParams.RUnlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001082 }
1083
mpagenko9c225032021-10-15 14:26:49 +00001084 pBaseFsm := oFsm.pAdaptFsm
1085 if pBaseFsm == nil {
1086 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
1087 return
1088 }
1089 // abort the download operation by sending an end software download message with invalid CRC and image size
1090 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx),
1091 oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
1092 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, 0, 0xFFFFFFFF)
1093 if err != nil {
1094 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: can't send EndSwDl request", log.Fields{"device-id": oFsm.deviceID})
1095 // Can't call FSM Event directly, decoupling it
1096 go func(a_pAFsm *AdapterFsm) {
1097 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1098 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1099 }
1100 }(pBaseFsm)
1101 return
1102 }
1103
1104 //avoid waiting in the enterXXX function here,
1105 // otherwise synchronous event calls (like from RxMessage processing) may block and block complete Rx processing then
1106 go oFsm.waitOnAbortEndSwDlResponse(ctx)
1107}
1108
1109//abortingDlEvaluateResponse waits for a channel indication with decision to proceed the FSM processing
1110func (oFsm *OnuUpgradeFsm) abortingDlEvaluateResponse(ctx context.Context,
1111 pBaseFsm *AdapterFsm, aResponseResult tEndSwDlResponseResult) bool {
1112 switch aResponseResult {
1113 case cEndSwDlResponseBusy: // indication for device busy, needs repetition
1114 if oFsm.waitCountEndSwDl == 0 {
1115 logger.Errorw(ctx, "aborting download: max limit of EndSwDl reached", log.Fields{
1116 "device-id": oFsm.deviceID})
1117 go func(a_pAFsm *AdapterFsm) {
1118 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1119 _ = a_pAFsm.pFsm.Event(upgradeEvRestart) //give up and let FSM terminate
1120 }
1121 }(pBaseFsm)
1122 } else {
1123 logger.Debugw(ctx, "aborting download: re-trigger sending abort SwDl", log.Fields{
1124 "device-id": oFsm.deviceID, "counter": oFsm.waitCountEndSwDl})
1125 oFsm.waitCountEndSwDl--
1126 oFsm.repeatAbort = true //repeated request in next round
1127 go func(a_pAFsm *AdapterFsm) {
1128 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1129 _ = a_pAFsm.pFsm.Event(upgradeEvReset) //which then re-triggers sending AbortSwDL
1130 }
1131 }(pBaseFsm)
1132 }
1133 return true
1134 case cEndSwDlResponseSuccess: // indication for success response
1135 logger.Infow(ctx, "aborting download: success response, terminating FSM", log.Fields{
1136 "device-id": oFsm.deviceID})
1137 case cEndSwDlResponseAbort: // indication for request to abort waiting for response
1138 logger.Infow(ctx, "aborting download: request to abort waiting, terminating FSM", log.Fields{
1139 "device-id": oFsm.deviceID})
1140 default:
1141 logger.Errorw(ctx, "aborting download: unknown channel indication, terminating FSM", log.Fields{
1142 "device-id": oFsm.deviceID})
1143 } //switch
1144 return false
1145}
1146
1147func (oFsm *OnuUpgradeFsm) enterRestarting(ctx context.Context, e *fsm.Event) {
1148 logger.Debugw(ctx, "OnuUpgradeFsm restarting", log.Fields{"device-id": oFsm.deviceID})
1149 pConfigUpgradeStateAFsm := oFsm.pAdaptFsm
1150 if pConfigUpgradeStateAFsm != nil {
mpagenko80622a52021-02-09 16:53:23 +00001151 // abort running message processing
1152 fsmAbortMsg := Message{
1153 Type: TestMsg,
1154 Data: TestMessage{
1155 TestMessageVal: AbortMessageProcessing,
1156 },
1157 }
mpagenko9c225032021-10-15 14:26:49 +00001158 pConfigUpgradeStateAFsm.commChan <- fsmAbortMsg
mpagenko80622a52021-02-09 16:53:23 +00001159
1160 //try to restart the FSM to 'disabled'
1161 // Can't call FSM Event directly, decoupling it
1162 go func(a_pAFsm *AdapterFsm) {
1163 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko9c225032021-10-15 14:26:49 +00001164 _ = a_pAFsm.pFsm.Event(upgradeEvDisable)
mpagenko80622a52021-02-09 16:53:23 +00001165 }
mpagenko9c225032021-10-15 14:26:49 +00001166 }(pConfigUpgradeStateAFsm)
mpagenko80622a52021-02-09 16:53:23 +00001167 }
1168}
1169
1170func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1171 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001172 // 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 +00001173 if oFsm.pDeviceHandler != nil {
1174 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenko9c225032021-10-15 14:26:49 +00001175 pLastUpgradeImageState := &voltha.ImageState{
1176 Version: oFsm.imageVersion,
1177 DownloadState: oFsm.volthaDownloadState,
1178 Reason: oFsm.volthaDownloadReason,
1179 ImageState: oFsm.volthaImageState,
1180 }
1181 go oFsm.pDeviceHandler.RemoveOnuUpgradeFsm(ctx, pLastUpgradeImageState)
mpagenko80622a52021-02-09 16:53:23 +00001182 }
1183}
1184
1185func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
1186 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
1187loop:
1188 for {
1189 // case <-ctx.Done():
1190 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
1191 // break loop
1192 message, ok := <-oFsm.pAdaptFsm.commChan
1193 if !ok {
1194 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
1195 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko9c225032021-10-15 14:26:49 +00001196 oFsm.abortOnOmciError(ctx, true)
mpagenko80622a52021-02-09 16:53:23 +00001197 break loop
1198 }
1199 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
1200
1201 switch message.Type {
1202 case TestMsg:
1203 msg, _ := message.Data.(TestMessage)
1204 if msg.TestMessageVal == AbortMessageProcessing {
1205 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
1206 break loop
1207 }
1208 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
1209 case OMCI:
1210 msg, _ := message.Data.(OmciMessage)
1211 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
1212 default:
1213 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
1214 "message.Type": message.Type})
1215 }
1216 }
1217 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
1218}
1219
mpagenko80622a52021-02-09 16:53:23 +00001220func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg OmciMessage) {
1221 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
1222 "msgType": msg.OmciMsg.MessageType})
1223
1224 switch msg.OmciMsg.MessageType {
1225 case omci.StartSoftwareDownloadResponseType:
1226 {
mpagenko9c225032021-10-15 14:26:49 +00001227 oFsm.handleRxStartSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001228 return
1229 } //StartSoftwareDownloadResponseType
1230 case omci.DownloadSectionResponseType:
1231 {
mpagenko9c225032021-10-15 14:26:49 +00001232 oFsm.handleRxSwSectionResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001233 return
mpagenko80622a52021-02-09 16:53:23 +00001234 } //DownloadSectionResponseType
1235 case omci.EndSoftwareDownloadResponseType:
1236 {
mpagenko9c225032021-10-15 14:26:49 +00001237 oFsm.handleRxEndSwDownloadResponse(ctx, msg)
mpagenko80622a52021-02-09 16:53:23 +00001238 return
1239 } //EndSoftwareDownloadResponseType
1240 case omci.ActivateSoftwareResponseType:
1241 {
1242 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1243 if msgLayer == nil {
1244 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1245 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001246 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001247 return
1248 }
1249 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1250 if !msgOk {
1251 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1252 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001253 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001254 return
1255 }
1256 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1257 "device-id": oFsm.deviceID, "data-fields": msgObj})
1258 if msgObj.Result != me.Success {
1259 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1260 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko9c225032021-10-15 14:26:49 +00001261 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001262 return
1263 }
mpagenko183647c2021-06-08 15:25:04 +00001264 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001265 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko9c225032021-10-15 14:26:49 +00001266 // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
mpagenko183647c2021-06-08 15:25:04 +00001267 oFsm.mutexUpgradeParams.Unlock()
1268 logger.Infow(ctx, "Expected ActivateSwResponse received",
1269 log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
1270 if oFsm.commitImage {
1271 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
1272 } else {
1273 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvActivationDone) // let the FSM wait for external commit request
1274 }
mpagenko80622a52021-02-09 16:53:23 +00001275 return
1276 }
mpagenko183647c2021-06-08 15:25:04 +00001277 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001278 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1279 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko9c225032021-10-15 14:26:49 +00001280 oFsm.abortOnOmciError(ctx, false)
mpagenko80622a52021-02-09 16:53:23 +00001281 return
1282 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001283 case omci.CommitSoftwareResponseType:
1284 {
1285 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1286 if msgLayer == nil {
1287 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1288 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001289 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001290 return
1291 }
1292 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1293 if !msgOk {
1294 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1295 log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001296 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001297 return
1298 }
mpagenkobf67a092021-03-17 09:52:28 +00001299 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001300 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1301 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko9c225032021-10-15 14:26:49 +00001302 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001303 return
mpagenkobf67a092021-03-17 09:52:28 +00001304 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001305 oFsm.mutexUpgradeParams.RLock()
mpagenko15ff4a52021-03-02 10:09:20 +00001306 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001307 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001308 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1309 //verifying committed image
1310 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
1311 return
1312 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001313 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001314 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1315 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko9c225032021-10-15 14:26:49 +00001316 oFsm.abortOnOmciError(ctx, false)
mpagenko15ff4a52021-03-02 10:09:20 +00001317 return
1318 } //CommitSoftwareResponseType
1319 case omci.GetResponseType:
1320 {
mpagenko9c225032021-10-15 14:26:49 +00001321 oFsm.handleRxSwGetResponse(ctx, msg)
mpagenko15ff4a52021-03-02 10:09:20 +00001322 return
1323 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001324 default:
1325 {
1326 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1327 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1328 return
1329 }
1330 }
1331}
1332
mpagenko9c225032021-10-15 14:26:49 +00001333func (oFsm *OnuUpgradeFsm) handleRxStartSwDownloadResponse(ctx context.Context, msg OmciMessage) {
1334 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
1335 if msgLayer == nil {
1336 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
1337 log.Fields{"device-id": oFsm.deviceID})
1338 oFsm.abortOnOmciError(ctx, false)
1339 return
1340 }
1341 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
1342 if !msgOk {
1343 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
1344 log.Fields{"device-id": oFsm.deviceID})
1345 oFsm.abortOnOmciError(ctx, false)
1346 return
1347 }
1348 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
1349 "device-id": oFsm.deviceID, "data-fields": msgObj})
1350 if msgObj.Result != me.Success {
1351 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
1352 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1353 oFsm.abortOnOmciError(ctx, false)
1354 return
1355 }
1356
1357 oFsm.mutexUpgradeParams.Lock()
1358 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1359 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1360 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
1361 // also response WindowSize = 0 is a valid number for used Window size 1
1362 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
1363 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
1364 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
1365 }
1366 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
1367 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
1368 oFsm.noOfWindows++
1369 }
1370 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
1371 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
1372 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
1373 oFsm.nextDownloadSectionsAbsolute = 0
1374 oFsm.nextDownloadSectionsWindow = 0
1375 oFsm.nextDownloadWindow = 0
1376
1377 oFsm.mutexUpgradeParams.Unlock()
1378 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
1379 return
1380 }
1381 oFsm.mutexUpgradeParams.Unlock()
1382 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1383 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1384 oFsm.abortOnOmciError(ctx, false)
1385} //handleRxStartSwDownloadResponse
1386
1387func (oFsm *OnuUpgradeFsm) handleRxSwSectionResponse(ctx context.Context, msg OmciMessage) {
1388 if oFsm.pAdaptFsm == nil {
1389 logger.Infow(ctx, "DlSectionResponse received - but FSM not really valid anymore", log.Fields{
1390 "device-id": oFsm.deviceID})
1391 return
1392 }
1393 if !oFsm.pAdaptFsm.pFsm.Is(upgradeStVerifyWindow) {
1394 //all the processing here is only relevant if the FSM is in state upgradeStVerifyWindow
1395 // otherwise this response can be ignored (may stem from a long-processing window send activity,
1396 // which is not anymore relevant based on intermediate (cancel) state transitions)
1397 logger.Infow(ctx, "DlSectionResponse received - but ignored", log.Fields{
1398 "device-id": oFsm.deviceID, "fsm-state": oFsm.pAdaptFsm.pFsm.Current()})
1399 return
1400 }
1401 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
1402 if msgLayer == nil {
1403 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
1404 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
1405 oFsm.abortOnOmciError(ctx, false)
1406 return
1407 }
1408 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
1409 if !msgOk {
1410 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
1411 log.Fields{"device-id": oFsm.deviceID})
1412 oFsm.abortOnOmciError(ctx, false)
1413 return
1414 }
1415 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
1416 "device-id": oFsm.deviceID, "data-fields": msgObj})
1417 if msgObj.Result != me.Success {
1418 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
1419 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1420 oFsm.abortOnOmciError(ctx, false)
1421 return
1422 }
1423 oFsm.mutexUpgradeParams.Lock()
1424 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1425 sectionNumber := msgObj.SectionNumber
1426 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
1427 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
1428
1429 oFsm.nextDownloadWindow++
1430 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
1431 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
1432 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
1433 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
1434 "expected section": oFsm.omciDownloadWindowSizeLast})
1435 oFsm.mutexUpgradeParams.Unlock()
1436 oFsm.abortOnOmciError(ctx, false)
1437 return
1438 }
1439 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
1440 //CRC computation for all data bytes of the file
1441 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
1442 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
1443 var byteSlice []byte = make([]byte, 4)
1444 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
1445 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
1446 oFsm.mutexUpgradeParams.Unlock()
1447 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
1448 return
1449 }
1450 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
1451 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
1452 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
1453 "expected section": oFsm.omciDownloadWindowSizeLimit})
1454 oFsm.mutexUpgradeParams.Unlock()
1455 oFsm.abortOnOmciError(ctx, false)
1456 return
1457 }
1458 oFsm.nextDownloadSectionsWindow = 0
1459 oFsm.mutexUpgradeParams.Unlock()
1460 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
1461 return
1462 }
1463 oFsm.mutexUpgradeParams.Unlock()
1464 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1465 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1466 oFsm.abortOnOmciError(ctx, false)
1467} //handleRxSwSectionResponse
1468
1469func (oFsm *OnuUpgradeFsm) handleRxEndSwDownloadResponse(ctx context.Context, msg OmciMessage) {
1470 inAbortingState := oFsm.pAdaptFsm.pFsm.Is(upgradeStAbortingDL)
1471
1472 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1473 if msgLayer == nil {
1474 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1475 log.Fields{"device-id": oFsm.deviceID})
1476 if !inAbortingState {
1477 oFsm.abortOnOmciError(ctx, false)
1478 } //else using error log and wait for another response or 'aborting' state timeout
1479 return
1480 }
1481 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1482 if !msgOk {
1483 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1484 log.Fields{"device-id": oFsm.deviceID})
1485 if !inAbortingState {
1486 oFsm.abortOnOmciError(ctx, false)
1487 } //else using error log and wait for another response or 'aborting' state timeout
1488 return
1489 }
1490 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1491 "device-id": oFsm.deviceID, "data-fields": msgObj})
1492 if msgObj.Result != me.Success {
1493 if msgObj.Result == me.DeviceBusy {
1494 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1495 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1496 "device-id": oFsm.deviceID})
1497 if inAbortingState {
1498 //if the EndSwDl was requested from state AbortingDL then use channel to indicate ONU busy/repeat indication
1499 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseBusy //repeat abort request
1500 }
mpagenko9c225032021-10-15 14:26:49 +00001501 return
1502 }
1503 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
1504 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1505 if inAbortingState {
1506 //if the EndSwDl was requested from state AbortingDL and response is error indication
1507 // that would be quite strange ONU behavior, no resolution from OnuAdapter, just let the FSM go on to disabled
1508 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseAbort //error indication to abort waiting on EndDownloadResponse
1509 } //else using error log and wait for another response or 'aborting' state timeout
1510 return
1511 }
1512 oFsm.mutexUpgradeParams.Lock()
1513 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1514 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
mpagenko9c225032021-10-15 14:26:49 +00001515 if inAbortingState {
1516 oFsm.mutexUpgradeParams.Unlock()
1517 //if the EndSwDl was requested from state AbortingDL then use channel to indicate abort acceptance
1518 oFsm.chReceiveAbortEndSwDlResponse <- cEndSwDlResponseSuccess //success
1519 return
1520 }
1521 if !oFsm.useAPIVersion43 {
1522 //in the older API version the image version check was not possible
1523 // - assume new loaded image as valid-inactive immediately
1524 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1525 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1526 oFsm.mutexUpgradeParams.Unlock()
1527 //use non-blocking channel (to be independent from receiver state)
1528 select {
1529 //use non-blocking channel to indicate that the download to ONU was successful
1530 case oFsm.chOnuDlReady <- true:
1531 default:
1532 }
1533 } else {
1534 oFsm.mutexUpgradeParams.Unlock()
1535 }
1536 //use asynchronous channel sending to let the FSM proceed
1537 select {
1538 case oFsm.chReceiveExpectedResponse <- true:
1539 default:
1540 }
1541 return
1542 }
1543 oFsm.mutexUpgradeParams.Unlock()
1544 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: ignoring",
1545 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1546 // no state abort in case of unexpected ImageId, just keep waiting for the correct one
1547} //handleRxEndSwDownloadResponse
1548
1549func (oFsm *OnuUpgradeFsm) handleRxSwGetResponse(ctx context.Context, msg OmciMessage) {
1550 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1551 if msgLayer == nil {
1552 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1553 log.Fields{"device-id": oFsm.deviceID})
1554 oFsm.abortOnOmciError(ctx, false)
1555 return
1556 }
1557 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1558 if !msgOk {
1559 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1560 log.Fields{"device-id": oFsm.deviceID})
1561 oFsm.abortOnOmciError(ctx, false)
1562 return
1563 }
1564 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1565 "device-id": oFsm.deviceID, "data-fields": msgObj})
1566 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1567 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1568 if msgObj.Result != me.Success {
1569 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1570 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1571 oFsm.abortOnOmciError(ctx, false)
1572 return
1573 }
1574 } else {
1575 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1576 log.Fields{"device-id": oFsm.deviceID})
1577 return
1578 }
1579
1580 meAttributes := msgObj.Attributes
1581 imageIsCommitted := meAttributes["IsCommitted"].(uint8)
1582 imageIsActive := meAttributes["IsActive"].(uint8)
1583 imageVersion := TrimStringFromMeOctet(meAttributes["Version"])
1584 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
1585 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1586 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
1587
1588 if oFsm.pAdaptFsm.pFsm.Current() == upgradeStCheckImageName {
1589 //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
1590 oFsm.verifyOnuSwStatusAfterDownload(ctx, msgObj.EntityInstance, imageVersion, imageIsActive, imageIsCommitted)
1591 return
1592 }
1593
1594 //assumed only relevant state here is upgradeStCheckCommitted
1595 oFsm.mutexUpgradeParams.Lock()
1596 oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
1597 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive {
1598 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1599 // indicated in the download image version string (version must be part of the image content itself)
1600 // so checking that might be quite unreliable
1601 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1602 // in all the API references, so it can and should be checked here now
1603 if oFsm.useAPIVersion43 {
1604 if imageVersion != oFsm.imageVersion {
1605 //new active version indicated on OMCI from ONU is not the expected version
1606 logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
1607 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1608 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1609 // TODO!!!: error treatment?
1610 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1611 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1612 oFsm.mutexUpgradeParams.Unlock()
1613 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1614 return
1615 }
1616 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1617 log.Fields{"device-id": oFsm.deviceID})
1618 }
1619 if imageIsCommitted == swIsCommitted {
1620 oFsm.upgradePhase = cUpgradeCommitted
1621 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
1622 //store the new commit flag to onuSwImageIndications (to keep them in sync)
1623 oFsm.pDevEntry.ModifySwImageActiveCommit(ctx, imageIsCommitted)
1624 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
1625 //deviceProcStatusUpdate not used anymore,
1626 // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
1627 oFsm.mutexUpgradeParams.Unlock()
1628 //releasing the upgrade FSM on success
1629 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1630 return
1631 }
1632 //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
1633 }
1634 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1635 oFsm.mutexUpgradeParams.Unlock()
1636 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1637 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1638 // TODO!!!: error treatment?
1639 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1640 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1641} //handleRxSwGetResponse
1642
1643func (oFsm *OnuUpgradeFsm) verifyOnuSwStatusAfterDownload(ctx context.Context, aInstanceID uint16,
1644 aImageVersion string, aImageIsActive uint8, aImageIsCommitted uint8) {
1645 oFsm.mutexUpgradeParams.Lock()
1646 if aInstanceID == oFsm.inactiveImageMeID && aImageIsActive == swIsInactive &&
1647 aImageIsCommitted == swIsUncommitted {
1648 if aImageVersion != oFsm.imageVersion {
1649 //new stored inactive version indicated on OMCI from ONU is not the expected version
1650 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
1651 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID,
1652 "onu-version": aImageVersion, "expected-version": oFsm.imageVersion})
1653 //download state is set when entering the reset state
1654 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1655 oFsm.mutexUpgradeParams.Unlock()
1656 //stop the running ONU download timer
1657 //use non-blocking channel (to be independent from receiver state)
1658 select {
1659 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1660 case oFsm.chOnuDlReady <- false:
1661 default:
1662 }
1663 // TODO!!!: error treatment?
1664 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1665 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1666 return
1667 }
1668 //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
1669 oFsm.upgradePhase = cUpgradeDownloaded
1670 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1671 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1672 //store the new inactive version to onuSwImageIndications (to keep them in sync)
1673 oFsm.pDevEntry.ModifySwImageInactiveVersion(ctx, oFsm.imageVersion)
1674 //proceed within upgrade FSM
1675 if oFsm.activateImage {
1676 //immediate activation requested
1677 oFsm.mutexUpgradeParams.Unlock()
1678 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
1679 log.Fields{"device-id": oFsm.deviceID})
1680 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRequestActivate)
1681 } else {
1682 //have to wait on explicit activation request
1683 oFsm.mutexUpgradeParams.Unlock()
1684 logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
1685 log.Fields{"device-id": oFsm.deviceID})
1686 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForActivate)
1687 }
1688 //use non-blocking channel (to be independent from receiver state)
1689 select {
1690 //use non-blocking channel to indicate that the download to ONU was successful
1691 case oFsm.chOnuDlReady <- true:
1692 default:
1693 }
1694 return
1695 }
1696 //not the expected image/image state
1697 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1698 oFsm.mutexUpgradeParams.Unlock()
1699 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1700 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": aInstanceID})
1701 // TODO!!!: error treatment?
1702 //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
1703 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1704} //verifyOnuSwStatusAfterDownload
1705
1706//abortOnOmciError aborts the upgrade processing with evAbort
1707// asynchronous/synchronous based on parameter aAsync
1708func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool) {
1709 oFsm.mutexUpgradeParams.Lock()
1710 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1711 oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
1712 oFsm.mutexUpgradeParams.Unlock()
1713 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1714 if oFsm.pAdaptFsm != nil {
1715 var err error
1716 if aAsync { //asynchronous call requested to ensure state transition
1717 go func(a_pAFsm *AdapterFsm) {
1718 if a_pAFsm.pFsm != nil {
1719 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1720 }
1721 }(oFsm.pAdaptFsm)
1722 } else {
1723 if oFsm.pAdaptFsm.pFsm != nil {
1724 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1725 }
1726 }
1727 if err != nil {
1728 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1729 "device-id": oFsm.deviceID, "error": err})
1730 }
1731 }
1732}
1733
mpagenkoc26d4c02021-05-06 14:27:57 +00001734//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
mpagenko9c225032021-10-15 14:26:49 +00001735// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
1736func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
1737 aWaitChannel chan bool) {
mpagenkoc26d4c02021-05-06 14:27:57 +00001738 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
mpagenko9c225032021-10-15 14:26:49 +00001739 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
mpagenkoc26d4c02021-05-06 14:27:57 +00001740 oFsm.isWaitingForAdapterDlResponse = true
1741 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko9c225032021-10-15 14:26:49 +00001742 aSyncChannel <- struct{}{}
mpagenko80622a52021-02-09 16:53:23 +00001743 select {
1744 // maybe be also some outside cancel (but no context modeled for the moment ...)
1745 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001746 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1747 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1748 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1749 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1750 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
mpagenko9c225032021-10-15 14:26:49 +00001751 //running into timeout here may still have the download to adapter active -> abort
1752 oFsm.pFileManager.CancelDownload(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +00001753 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1754 oFsm.isWaitingForAdapterDlResponse = false
1755 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko9c225032021-10-15 14:26:49 +00001756 oFsm.mutexUpgradeParams.Lock()
1757 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1758 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'DOWNLOAD_TO_ADAPTER_TIMEOUT' would be better (proto)
1759 oFsm.mutexUpgradeParams.Unlock()
1760 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1761 if oFsm.pAdaptFsm != nil && oFsm.pAdaptFsm.pFsm != nil {
1762 err := oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1763 if err != nil {
1764 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1765 "device-id": oFsm.deviceID, "error": err})
1766 }
mpagenko80622a52021-02-09 16:53:23 +00001767 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001768 return
1769
1770 case success := <-aWaitChannel:
1771 if success {
1772 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1773 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1774 oFsm.isWaitingForAdapterDlResponse = false
1775 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1776 //let the upgrade process proceed
1777 pUpgradeFsm := oFsm.pAdaptFsm
1778 if pUpgradeFsm != nil {
1779 _ = pUpgradeFsm.pFsm.Event(upgradeEvPrepareSwDownload)
1780 } else {
1781 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1782 }
1783 return
1784 }
mpagenko9c225032021-10-15 14:26:49 +00001785 // waiting was aborted (assumed here to be caused by
1786 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001787 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1788 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1789 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1790 oFsm.isWaitingForAdapterDlResponse = false
1791 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001792 return
mpagenko80622a52021-02-09 16:53:23 +00001793 }
1794}
mpagenkoc26d4c02021-05-06 14:27:57 +00001795
1796//waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1797func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1798 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1799 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1800 "duration": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001801 select {
1802 // maybe be also some outside cancel (but no context modeled for the moment ...)
1803 // case <-ctx.Done():
1804 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1805 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1806 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1807 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001808 //the upgrade process has to be aborted
mpagenko9c225032021-10-15 14:26:49 +00001809 oFsm.abortOnOmciError(ctx, false)
mpagenkoc26d4c02021-05-06 14:27:57 +00001810 return
1811
1812 case success := <-aWaitChannel:
1813 if success {
1814 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001815 //all fine, let the FSM proceed like defined from the sender of this event
1816 return
1817 }
1818 // waiting was aborted (assumed here to be caused by
mpagenko9c225032021-10-15 14:26:49 +00001819 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001820 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001821 return
1822 }
1823}
mpagenko9c225032021-10-15 14:26:49 +00001824
1825//waitOnAbortEndSwDlResponse waits for either abort/success or timeout of EndSwDownload (for abortion)
1826func (oFsm *OnuUpgradeFsm) waitOnAbortEndSwDlResponse(ctx context.Context) {
1827 logger.Debugw(ctx, "OnuUpgradeFsm start wait for EndSwDl response (abort)", log.Fields{"device-id": oFsm.deviceID})
1828 select {
1829 case <-time.After(oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second):
1830 logger.Warnw(ctx, "OnuUpgradeFsm aborting download: timeout - no response received", log.Fields{"device-id": oFsm.deviceID})
1831 pUpgradeFsm := oFsm.pAdaptFsm
1832 if pUpgradeFsm != nil {
1833 _ = pUpgradeFsm.pFsm.Event(upgradeEvRestart)
1834 } else {
1835 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1836 }
1837 return
1838 case response := <-oFsm.chReceiveAbortEndSwDlResponse:
1839 logger.Debugw(ctx, "OnuUpgradeFsm aborting download: response received",
1840 log.Fields{"device-id": oFsm.deviceID, "response": response})
1841 pUpgradeFsm := oFsm.pAdaptFsm
1842 if pUpgradeFsm != nil {
1843 if oFsm.abortingDlEvaluateResponse(ctx, pUpgradeFsm, response) {
1844 return //event sent from function already
1845 }
1846 _ = pUpgradeFsm.pFsm.Event(upgradeEvRestart)
1847 } else {
1848 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1849 }
1850 return
1851 } //select
1852}
1853
1854//stateUpdateOnReset writes the download and/or image state on entering the reset state according to FSM internal indications
1855func (oFsm *OnuUpgradeFsm) stateUpdateOnReset(ctx context.Context) {
1856 oFsm.mutexUpgradeParams.Lock()
1857 defer oFsm.mutexUpgradeParams.Unlock()
1858 if !oFsm.conditionalCancelRequested {
1859 switch oFsm.upgradePhase {
1860 case cUpgradeUndefined, cUpgradeDownloading: //coming from downloading
1861 //make sure the download state is only changed in case the device has still been downloading
1862 if oFsm.volthaDownloadReason == voltha.ImageState_CANCELLED_ON_REQUEST {
1863 // indication for termination on request
1864 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
1865 } else if oFsm.volthaDownloadReason != voltha.ImageState_NO_ERROR {
1866 // indication for termination on failure
1867 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1868 }
1869 //reset the image state from Downloading in this case
1870 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1871 //in all other upgrade phases the last set download state remains valid
1872 case cUpgradeActivating:
1873 //reset the image state from Activating in this case
1874 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATION_ABORTED
1875 case cUpgradeCommitting: // indication for request to abort waiting for response
1876 //reset the image state from Activating in this case
1877 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
1878 //default: in all other upgrade phases keep the last set imageState
1879 } //switch
1880 } else {
1881 //when reaching reset state with conditional cancel that can only result from ONU related problems
1882 // (mostly ONU down indication) - derived from resetFsms call
1883 // and it can only be related to the downloading-to-ONU phase (no need to check that additionally)
1884 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1885 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1886 //reset the image state from Downloading in this case
1887 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1888 }
1889}