blob: 8e8a82e6a81b9f35fa996b612a212b1ccdbddfb2 [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"
khenaidoo7d3c5582021-08-11 18:09:44 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/log"
33 "github.com/opencord/voltha-protos/v5/go/voltha"
mpagenko80622a52021-02-09 16:53:23 +000034)
35
36const cMaxUint32 = ^uint32(0)
37
38const (
39 // internal predefined values - some off them should later be configurable (perhaps with theses as defaults)
40 cOmciDownloadSectionSize = 31 //in bytes
41 cOmciDownloadWindowSizeLimit = 31 //in sections for window offset (windowSize(32)-1)
42 //cOmciDownloadWindowRetryMax = 2 // max attempts for a specific window
mpagenkoc26d4c02021-05-06 14:27:57 +000043 cOmciSectionInterleaveMilliseconds = 0 //DownloadSection interleave time in milliseconds (0 for no delay)
44 cOmciEndSwDlDelaySeconds = 1 //End Software Download delay after last section (may be also configurable?)
45 cWaitCountEndSwDl = 6 //maximum number of EndSwDl requests
46 cWaitDelayEndSwDlSeconds = 10 //duration, how long is waited before next request on EndSwDl
mpagenko80622a52021-02-09 16:53:23 +000047 //cOmciDownloadCompleteTimeout = 5400 //in s for the complete timeout (may be better scale to image size/ noOfWindows)
48)
49
50const (
51 // events of config PON ANI port FSM
52 upgradeEvStart = "upgradeEvStart"
Holger Hildebrandt288d9472021-09-06 10:47:53 +000053 upgradeEvDisable = "upgradeEvDisable"
mpagenkoc26d4c02021-05-06 14:27:57 +000054 upgradeEvAdapterDownload = "upgradeEvAdapterDownload"
mpagenko80622a52021-02-09 16:53:23 +000055 upgradeEvPrepareSwDownload = "upgradeEvPrepareSwDownload"
56 upgradeEvRxStartSwDownload = "upgradeEvRxStartSwDownload"
57 upgradeEvWaitWindowAck = "upgradeEvWaitWindowAck"
58 upgradeEvContinueNextWindow = "upgradeEvContinueNextWindow"
59 upgradeEvEndSwDownload = "upgradeEvEndSwDownload"
mpagenko59498c12021-03-18 14:15:15 +000060 upgradeEvWaitEndDownload = "upgradeEvWaitEndDownload"
61 upgradeEvContinueFinalize = "upgradeEvContinueFinalize"
mpagenko38662d02021-08-11 09:45:19 +000062 upgradeEvCheckImageName = "upgradeEvCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +000063 upgradeEvWaitForActivate = "upgradeEvWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000064 upgradeEvRequestActivate = "upgradeEvRequestActivate"
mpagenko183647c2021-06-08 15:25:04 +000065 upgradeEvActivationDone = "upgradeEvActivationDone"
mpagenko80622a52021-02-09 16:53:23 +000066 upgradeEvWaitForCommit = "upgradeEvWaitForCommit"
67 upgradeEvCommitSw = "upgradeEvCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +000068 upgradeEvCheckCommitted = "upgradeEvCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +000069
70 //upgradeEvTimeoutSimple = "upgradeEvTimeoutSimple"
71 //upgradeEvTimeoutMids = "upgradeEvTimeoutMids"
Holger Hildebrandt288d9472021-09-06 10:47:53 +000072 upgradeEvReset = "upgradeEvReset"
73 upgradeEvAbort = "upgradeEvAbort"
74 upgradeEvRestart = "upgradeEvRestart"
75 upgradeEvAbortSwDownload = "upgradeEvAbortSwDownload"
mpagenko80622a52021-02-09 16:53:23 +000076)
77
78const (
79 // states of config PON ANI port FSM
80 upgradeStDisabled = "upgradeStDisabled"
81 upgradeStStarting = "upgradeStStarting"
mpagenkoc26d4c02021-05-06 14:27:57 +000082 upgradeStWaitingAdapterDL = "upgradeStWaitingAdapterDL"
mpagenko80622a52021-02-09 16:53:23 +000083 upgradeStPreparingDL = "upgradeStPreparingDL"
84 upgradeStDLSection = "upgradeStDLSection"
85 upgradeStVerifyWindow = "upgradeStVerifyWindow"
86 upgradeStFinalizeDL = "upgradeStFinalizeDL"
mpagenko59498c12021-03-18 14:15:15 +000087 upgradeStWaitEndDL = "upgradeStWaitEndDL"
mpagenko38662d02021-08-11 09:45:19 +000088 upgradeStCheckImageName = "upgradeStCheckImageName"
mpagenkoc26d4c02021-05-06 14:27:57 +000089 upgradeStWaitForActivate = "upgradeStWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000090 upgradeStRequestingActivate = "upgradeStRequestingActivate"
mpagenko183647c2021-06-08 15:25:04 +000091 upgradeStActivated = "upgradeStActivated"
mpagenko80622a52021-02-09 16:53:23 +000092 upgradeStWaitForCommit = "upgradeStWaitForCommit"
93 upgradeStCommitSw = "upgradeStCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +000094 upgradeStCheckCommitted = "upgradeStCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +000095 upgradeStResetting = "upgradeStResetting"
Holger Hildebrandt288d9472021-09-06 10:47:53 +000096 upgradeStRestarting = "upgradeStRestarting"
97 upgradeStAbortingDL = "upgradeStAbortingDL"
mpagenko80622a52021-02-09 16:53:23 +000098)
99
100//required definition for IdleState detection for activities on OMCI
101const cOnuUpgradeFsmIdleState = upgradeStWaitForCommit
102
103//OnuUpgradeFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
104type OnuUpgradeFsm struct {
105 pDeviceHandler *deviceHandler
106 pDownloadManager *adapterDownloadManager
mpagenkoc26d4c02021-05-06 14:27:57 +0000107 pFileManager *fileDownloadManager //used from R2.8 with new API version
mpagenko80622a52021-02-09 16:53:23 +0000108 deviceID string
mpagenko38662d02021-08-11 09:45:19 +0000109 pDevEntry *OnuDeviceEntry
mpagenko80622a52021-02-09 16:53:23 +0000110 pOmciCC *omciCC
111 pOnuDB *onuDeviceDB
112 requestEvent OnuDeviceEvent
113 //omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
mpagenkoc26d4c02021-05-06 14:27:57 +0000114 pAdaptFsm *AdapterFsm
115 pImageDsc *voltha.ImageDownload
116 imageBuffer []byte
117 origImageLength uint32 //as also limited by OMCI
118 imageCRC uint32 //as per OMCI - ITU I.363.5 crc
119 imageLength uint32 //including last bytes padding
120 omciDownloadWindowSizeLimit uint8 //windowSize-1 in sections
121 omciDownloadWindowSizeLast uint8 //number of sections in last window
122 noOfSections uint32 //uint32 range for sections should be sufficient for very long images
123 nextDownloadSectionsAbsolute uint32 //number of next section to download in overall image
124 nextDownloadSectionsWindow uint8 //number of next section to download within current window
125 noOfWindows uint32 //uint32 range for windows should be sufficient for very long images
126 nextDownloadWindow uint32 //number of next window to download
127 inactiveImageMeID uint16 //ME-ID of the inactive image
128 downloadToOnuTimeout4MB time.Duration //timeout for downloading the image to the ONU for a 4MB image slice
129 omciSectionInterleaveDelay time.Duration //DownloadSectionInterleave delay in milliseconds
130 delayEndSwDl bool //flag to provide a delay between last section and EndSwDl
131 pLastTxMeInstance *me.ManagedEntity
132 waitCountEndSwDl uint8 //number, how often is waited for EndSwDl at maximum
133 waitDelayEndSwDl time.Duration //duration, how long is waited before next request on EndSwDl
134 chReceiveExpectedResponse chan bool
mpagenkoaa3afe92021-05-21 16:20:58 +0000135 useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
136 mutexUpgradeParams sync.RWMutex //mutex to protect members for parallel function requests and omci response processing
137 imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
138 imageIdentifier string //name of the image as used in the adapter
mpagenkoc26d4c02021-05-06 14:27:57 +0000139 mutexIsAwaitingAdapterDlResponse sync.RWMutex
140 chAdapterDlReady chan bool
141 isWaitingForAdapterDlResponse bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000142 chOnuDlReady chan bool
mpagenkoc26d4c02021-05-06 14:27:57 +0000143 activateImage bool
144 commitImage bool
mpagenko38662d02021-08-11 09:45:19 +0000145 mutexAbortRequest sync.RWMutex
146 abortRequested voltha.ImageState_ImageFailureReason
147 conditionalCancelRequested bool
mpagenkoaa3afe92021-05-21 16:20:58 +0000148 volthaDownloadState voltha.ImageState_ImageDownloadState
149 volthaDownloadReason voltha.ImageState_ImageFailureReason
150 volthaImageState voltha.ImageState_ImageActivationState
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000151 isEndSwDlOpen bool
152 chReceiveAbortEndSwDlResponse chan bool
mpagenko80622a52021-02-09 16:53:23 +0000153}
154
155//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
156// of ONU UNI ports via OMCI
157func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler *deviceHandler,
mpagenko15ff4a52021-03-02 10:09:20 +0000158 apDevEntry *OnuDeviceEntry, apOnuDB *onuDeviceDB,
mpagenko80622a52021-02-09 16:53:23 +0000159 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message) *OnuUpgradeFsm {
160 instFsm := &OnuUpgradeFsm{
mpagenko59498c12021-03-18 14:15:15 +0000161 pDeviceHandler: apDeviceHandler,
162 deviceID: apDeviceHandler.deviceID,
mpagenko38662d02021-08-11 09:45:19 +0000163 pDevEntry: apDevEntry,
mpagenko59498c12021-03-18 14:15:15 +0000164 pOmciCC: apDevEntry.PDevOmciCC,
165 pOnuDB: apOnuDB,
166 requestEvent: aRequestEvent,
167 omciDownloadWindowSizeLimit: cOmciDownloadWindowSizeLimit,
168 omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000169 downloadToOnuTimeout4MB: apDeviceHandler.pOpenOnuAc.dlToOnuTimeout4M,
mpagenko59498c12021-03-18 14:15:15 +0000170 waitCountEndSwDl: cWaitCountEndSwDl,
171 waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
mpagenkoaa3afe92021-05-21 16:20:58 +0000172 volthaDownloadState: voltha.ImageState_DOWNLOAD_STARTED, //if FSM created we can assume that the download (to adapter) really started
173 volthaDownloadReason: voltha.ImageState_NO_ERROR,
174 volthaImageState: voltha.ImageState_IMAGE_UNKNOWN,
mpagenko38662d02021-08-11 09:45:19 +0000175 abortRequested: voltha.ImageState_NO_ERROR,
mpagenko80622a52021-02-09 16:53:23 +0000176 }
mpagenko59498c12021-03-18 14:15:15 +0000177 instFsm.chReceiveExpectedResponse = make(chan bool)
mpagenkoc26d4c02021-05-06 14:27:57 +0000178 instFsm.chAdapterDlReady = make(chan bool)
179 instFsm.chOnuDlReady = make(chan bool)
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000180 instFsm.chReceiveAbortEndSwDlResponse = make(chan bool)
mpagenko80622a52021-02-09 16:53:23 +0000181
182 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
183 if instFsm.pAdaptFsm == nil {
184 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
185 "device-id": instFsm.deviceID})
186 return nil
187 }
188 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
189 upgradeStDisabled,
190 fsm.Events{
191 {Name: upgradeEvStart, Src: []string{upgradeStDisabled}, Dst: upgradeStStarting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000192 {Name: upgradeEvAdapterDownload, Src: []string{upgradeStStarting}, Dst: upgradeStWaitingAdapterDL},
193 {Name: upgradeEvPrepareSwDownload, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL}, Dst: upgradeStPreparingDL},
mpagenko80622a52021-02-09 16:53:23 +0000194 {Name: upgradeEvRxStartSwDownload, Src: []string{upgradeStPreparingDL}, Dst: upgradeStDLSection},
195 {Name: upgradeEvWaitWindowAck, Src: []string{upgradeStDLSection}, Dst: upgradeStVerifyWindow},
196 {Name: upgradeEvContinueNextWindow, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStDLSection},
197 {Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
mpagenko59498c12021-03-18 14:15:15 +0000198 {Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
199 {Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
mpagenko38662d02021-08-11 09:45:19 +0000200 //upgradeStCheckImageName only used with useAPIVersion43
201 {Name: upgradeEvCheckImageName, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStCheckImageName},
202 //upgradeEvWaitForActivate state transitions depend on useAPIVersion43
203 {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL, upgradeStCheckImageName}, Dst: upgradeStWaitForActivate},
204 //upgradeEvRequestActivate state transitions depend on useAPIVersion43
205 {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStCheckImageName,
206 upgradeStWaitForActivate}, Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
mpagenko183647c2021-06-08 15:25:04 +0000207 {Name: upgradeEvActivationDone, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStActivated},
mpagenko80622a52021-02-09 16:53:23 +0000208 {Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
mpagenko1f8e8822021-06-25 14:10:21 +0000209 {Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
210 upgradeStActivated}, Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
mpagenko15ff4a52021-03-02 10:09:20 +0000211 {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000212
213 /*
214 {Name: upgradeEvTimeoutSimple, Src: []string{
215 upgradeStCreatingDot1PMapper, upgradeStCreatingMBPCD, upgradeStSettingTconts, upgradeStSettingDot1PMapper}, Dst: upgradeStStarting},
216 {Name: upgradeEvTimeoutMids, Src: []string{
217 upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
218 */
219 // exceptional treatments
mpagenko1f8e8822021-06-25 14:10:21 +0000220 //on upgradeEvReset: upgradeStRequestingActivate, upgradeStWaitForCommit and upgradeStActivated are not reset
221 // (to let the FSM survive the expected OnuDown indication)
mpagenkoc26d4c02021-05-06 14:27:57 +0000222 {Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko38662d02021-08-11 09:45:19 +0000223 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
224 upgradeStWaitForActivate,
mpagenko1f8e8822021-06-25 14:10:21 +0000225 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000226 Dst: upgradeStResetting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000227 {Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
mpagenko38662d02021-08-11 09:45:19 +0000228 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
229 upgradeStWaitForActivate,
230 upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit,
231 upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000232 Dst: upgradeStResetting},
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000233 {Name: upgradeEvAbortSwDownload, Src: []string{upgradeStResetting}, Dst: upgradeStAbortingDL},
234 {Name: upgradeEvRestart, Src: []string{upgradeStResetting, upgradeStAbortingDL}, Dst: upgradeStRestarting},
235 {Name: upgradeEvDisable, Src: []string{upgradeStRestarting}, Dst: upgradeStDisabled},
mpagenko80622a52021-02-09 16:53:23 +0000236 },
237 fsm.Callbacks{
238 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
239 "enter_" + upgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
mpagenkoc26d4c02021-05-06 14:27:57 +0000240 "enter_" + upgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000241 "enter_" + upgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
242 "enter_" + upgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
243 "enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
244 "enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
mpagenko59498c12021-03-18 14:15:15 +0000245 "enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
mpagenko38662d02021-08-11 09:45:19 +0000246 "enter_" + upgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000247 "enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
248 "enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
mpagenko15ff4a52021-03-02 10:09:20 +0000249 "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000250 "enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000251 "enter_" + upgradeStAbortingDL: func(e *fsm.Event) { instFsm.enterAbortingDL(ctx, e) },
252 "enter_" + upgradeStRestarting: func(e *fsm.Event) { instFsm.enterRestarting(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000253 "enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
254 },
255 )
256 if instFsm.pAdaptFsm.pFsm == nil {
257 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
258 "device-id": instFsm.deviceID})
259 return nil
260 }
261
262 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
263 return instFsm
264}
265
266//SetDownloadParams configures the needed parameters for a specific download to the ONU
mpagenkoc26d4c02021-05-06 14:27:57 +0000267// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000268func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
269 apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
mpagenko80622a52021-02-09 16:53:23 +0000270 pBaseFsm := oFsm.pAdaptFsm.pFsm
271 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
mpagenkoaa3afe92021-05-21 16:20:58 +0000272 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000273 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
274 "device-id": oFsm.deviceID, "image-description": apImageDsc})
mpagenko15ff4a52021-03-02 10:09:20 +0000275 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000276 oFsm.pImageDsc = apImageDsc
277 oFsm.pDownloadManager = apDownloadManager
Holger Hildebrandtac1e0592021-06-03 15:16:49 +0000278 oFsm.activateImage = true
279 oFsm.commitImage = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000280 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000281
282 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000283 // let the upgrade FSM proceed to PreparingDL
mpagenko80622a52021-02-09 16:53:23 +0000284 _ = aPBaseFsm.Event(upgradeEvPrepareSwDownload)
285 }(pBaseFsm)
286 return nil
287 }
288 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
289 "device-id": oFsm.deviceID})
290 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
291}
292
mpagenkoc26d4c02021-05-06 14:27:57 +0000293//SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
294// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
295// called from 'new' API Download_onu_image
296func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
297 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *fileDownloadManager,
Holger Hildebrandtac010732021-06-02 13:35:39 +0000298 aImageIdentifier string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000299 oFsm.mutexUpgradeParams.Lock()
300 var pBaseFsm *fsm.FSM = nil
301 if oFsm.pAdaptFsm != nil {
302 pBaseFsm = oFsm.pAdaptFsm.pFsm
303 }
304 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
305 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
306 "device-id": oFsm.deviceID, "image-description": apImageRequest})
307 oFsm.useAPIVersion43 = true
308 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
309 oFsm.pFileManager = apDownloadManager
310 oFsm.imageIdentifier = aImageIdentifier
311 oFsm.imageVersion = apImageRequest.Image.Version
312 oFsm.activateImage = apImageRequest.ActivateOnSuccess
313 oFsm.commitImage = apImageRequest.CommitOnSuccess
mpagenkoc26d4c02021-05-06 14:27:57 +0000314 //TODO: currently straightforward options activate and commit are expected to be set and (unconditionally) done
315 // for separate handling of these options the FSM must accordingly branch from the concerned states - later
316 oFsm.mutexUpgradeParams.Unlock()
317 _ = pBaseFsm.Event(upgradeEvAdapterDownload) //no need to call the FSM event in background here
318 return nil
319 }
320 oFsm.mutexUpgradeParams.Unlock()
321 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
322 "device-id": oFsm.deviceID})
323 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
324}
325
326//SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
327// called from 'new' API Activate_onu_image
328func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
329 aImageIdentifier string, aCommit bool) error {
330 oFsm.mutexUpgradeParams.Lock()
331 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
332 // (as long as the Imageidentifier is correct)
333 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
334 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
335 if aImageIdentifier != oFsm.imageIdentifier {
336 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
337 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
338 oFsm.mutexUpgradeParams.Unlock()
339 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
340 oFsm.deviceID))
341 }
342 oFsm.activateImage = true
343 oFsm.commitImage = aCommit
mpagenkoc26d4c02021-05-06 14:27:57 +0000344 var pBaseFsm *fsm.FSM = nil
345 if oFsm.pAdaptFsm != nil {
346 pBaseFsm = oFsm.pAdaptFsm.pFsm
347 }
348 if pBaseFsm != nil {
349 if pBaseFsm.Is(upgradeStWaitForActivate) {
mpagenko38662d02021-08-11 09:45:19 +0000350 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
351 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000352 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
353 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
mpagenko38662d02021-08-11 09:45:19 +0000354 } else {
355 oFsm.mutexUpgradeParams.Unlock()
356 logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
357 "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
mpagenkoc26d4c02021-05-06 14:27:57 +0000358 }
359 return nil
360 }
361 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
362 "device-id": oFsm.deviceID})
363 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
364}
365
366//SetActivationParamsStart starts upgrade processing with immediate activation
367// called from 'new' API Activate_onu_image
368func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
369 oFsm.mutexUpgradeParams.Lock()
370 var pBaseFsm *fsm.FSM = nil
371 if oFsm.pAdaptFsm != nil {
372 pBaseFsm = oFsm.pAdaptFsm.pFsm
373 }
374 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
375 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
376 "device-id": oFsm.deviceID, "image-version": aImageVersion})
377 oFsm.useAPIVersion43 = true
378 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
379 oFsm.imageVersion = aImageVersion
380 oFsm.activateImage = true
381 oFsm.commitImage = aCommit
mpagenko38662d02021-08-11 09:45:19 +0000382 // indicate start of the upgrade activity
383 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
384 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE //as simply applied for inactive image
mpagenkoc26d4c02021-05-06 14:27:57 +0000385 oFsm.mutexUpgradeParams.Unlock()
386 //directly request the FSM to activate the image
387 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
388 return nil
389 }
390 oFsm.mutexUpgradeParams.Unlock()
391 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
392 "device-id": oFsm.deviceID})
393 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
394}
395
396//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
397// called from 'new' API Commit_onu_image
mpagenko38662d02021-08-11 09:45:19 +0000398func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
399 aImageIdentifier string, aImageVersion string) error {
mpagenkoc26d4c02021-05-06 14:27:57 +0000400 oFsm.mutexUpgradeParams.Lock()
401 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
402 // (as long as the Imageidentifier is correct)
403 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
404 "device-id": oFsm.deviceID, "image-id": aImageIdentifier})
mpagenko38662d02021-08-11 09:45:19 +0000405 if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000406 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
mpagenko38662d02021-08-11 09:45:19 +0000407 "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
408 "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
mpagenkoc26d4c02021-05-06 14:27:57 +0000409 oFsm.mutexUpgradeParams.Unlock()
410 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
411 oFsm.deviceID))
412 }
413 oFsm.commitImage = true
mpagenko38662d02021-08-11 09:45:19 +0000414 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
mpagenkoc26d4c02021-05-06 14:27:57 +0000415 oFsm.mutexUpgradeParams.Unlock()
416 var pBaseFsm *fsm.FSM = nil
417 if oFsm.pAdaptFsm != nil {
418 pBaseFsm = oFsm.pAdaptFsm.pFsm
419 }
420 if pBaseFsm != nil {
mpagenko183647c2021-06-08 15:25:04 +0000421 //let the FSM decide if it is ready to process the event
422 logger.Debugw(ctx, "OnuUpgradeFsm requesting commit",
423 log.Fields{"device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
424 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
mpagenkoc26d4c02021-05-06 14:27:57 +0000425 return nil
426 }
mpagenko38662d02021-08-11 09:45:19 +0000427 //should never occur
mpagenkoc26d4c02021-05-06 14:27:57 +0000428 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
429 "device-id": oFsm.deviceID})
430 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
431}
432
433//SetCommitmentParamsStart starts upgrade processing with immediate commitment
434// called from 'new' API Commit_onu_image
435func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
436 oFsm.mutexUpgradeParams.Lock()
437 var pBaseFsm *fsm.FSM = nil
438 if oFsm.pAdaptFsm != nil {
439 pBaseFsm = oFsm.pAdaptFsm.pFsm
440 }
441 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
442 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
443 "device-id": oFsm.deviceID, "image-version": aImageVersion})
444 oFsm.useAPIVersion43 = true
445 oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
446 oFsm.imageVersion = aImageVersion
447 oFsm.commitImage = true
mpagenko38662d02021-08-11 09:45:19 +0000448 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
449 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE //as simply applied for active image
mpagenkoc26d4c02021-05-06 14:27:57 +0000450 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +0000451 //directly request the FSM to commit the image
mpagenkoc26d4c02021-05-06 14:27:57 +0000452 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
453 return nil
454 }
455 oFsm.mutexUpgradeParams.Unlock()
456 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
457 "device-id": oFsm.deviceID})
458 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
459}
460
mpagenko1f8e8822021-06-25 14:10:21 +0000461//GetCommitFlag delivers the commit flag that was configured here
462func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
463 oFsm.mutexUpgradeParams.RLock()
464 defer oFsm.mutexUpgradeParams.RUnlock()
465 return oFsm.commitImage
466}
467
mpagenko38662d02021-08-11 09:45:19 +0000468//GetImageStates delivers the download/image states as per device proto buf definition
mpagenkoaa3afe92021-05-21 16:20:58 +0000469func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
mpagenko38662d02021-08-11 09:45:19 +0000470 aImageIdentifier string, aVersion string) *voltha.ImageState {
mpagenkoaa3afe92021-05-21 16:20:58 +0000471 pImageState := &voltha.ImageState{}
mpagenko38662d02021-08-11 09:45:19 +0000472 pImageState.Version = aVersion //version as requested
mpagenkoaa3afe92021-05-21 16:20:58 +0000473 // check if the request refers to some active image/version of the processing
474 oFsm.mutexUpgradeParams.RLock()
475 if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
476 pImageState.DownloadState = oFsm.volthaDownloadState
477 pImageState.Reason = oFsm.volthaDownloadReason
478 pImageState.ImageState = oFsm.volthaImageState
479 } else {
480 pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
481 pImageState.Reason = voltha.ImageState_NO_ERROR
482 pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
483 }
484 oFsm.mutexUpgradeParams.RUnlock()
mpagenko38662d02021-08-11 09:45:19 +0000485 return pImageState
mpagenkoaa3afe92021-05-21 16:20:58 +0000486}
487
mpagenko38662d02021-08-11 09:45:19 +0000488//GetSpecificImageState delivers ImageState of the download/image states as per device proto buf definition
489func (oFsm *OnuUpgradeFsm) GetSpecificImageState(ctx context.Context) voltha.ImageState_ImageActivationState {
490 oFsm.mutexUpgradeParams.RLock()
491 imageState := oFsm.volthaImageState
492 oFsm.mutexUpgradeParams.RUnlock()
493 return imageState
494}
495
496//SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
497func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
mpagenko183647c2021-06-08 15:25:04 +0000498 oFsm.mutexUpgradeParams.Lock()
499 defer oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +0000500 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
501 if !oFsm.commitImage {
502 //if commit is not additionally set, regard the upgrade activity as successful
503 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED //better choice would be 'UpgradeState=Succeeded'
504 }
505}
506
507//GetImageVersion delivers image-version of the running upgrade
508func (oFsm *OnuUpgradeFsm) GetImageVersion(ctx context.Context) string {
509 oFsm.mutexUpgradeParams.RLock()
510 imageVersion := oFsm.imageVersion
511 oFsm.mutexUpgradeParams.RUnlock()
512 return imageVersion
mpagenko183647c2021-06-08 15:25:04 +0000513}
514
mpagenkoc26d4c02021-05-06 14:27:57 +0000515//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko38662d02021-08-11 09:45:19 +0000516func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
517 aReason voltha.ImageState_ImageFailureReason) {
518 oFsm.mutexAbortRequest.Lock()
519 oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
520 oFsm.mutexAbortRequest.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000521 //mutex protection is required for possible concurrent access to FSM members
522 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
523 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
524 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
525 if oFsm.isWaitingForAdapterDlResponse {
526 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
527 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
528 oFsm.chAdapterDlReady <- false
529 } else {
530 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
531 }
532 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
533
534 // 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 +0000535 // specific here: See definition of state changes: some states are excluded from reset for possible later commit
mpagenkoc26d4c02021-05-06 14:27:57 +0000536 pAdaptFsm := oFsm.pAdaptFsm
537 if pAdaptFsm != nil {
538 // calling FSM events in background to avoid blocking of the caller
539 go func(aPAFsm *AdapterFsm) {
540 if aPAFsm.pFsm != nil {
541 if aPAFsm.pFsm.Is(upgradeStWaitEndDL) {
mpagenko38662d02021-08-11 09:45:19 +0000542 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
mpagenkoc26d4c02021-05-06 14:27:57 +0000543 }
mpagenko38662d02021-08-11 09:45:19 +0000544 // in case of state-conditional request the
545
546 var err error
547 if abCompleteAbort {
548 oFsm.mutexUpgradeParams.Lock()
549 //any previous lingering conditional cancelRequest is superseded by this abortion
550 oFsm.conditionalCancelRequested = false
551 if aReason == voltha.ImageState_CANCELLED_ON_REQUEST {
552 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
553 } else {
554 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
555 }
556 oFsm.volthaDownloadReason = aReason
557 oFsm.mutexUpgradeParams.Unlock()
558 err = aPAFsm.pFsm.Event(upgradeEvAbort) //as unconditional default FSM cancellation
559 } else {
560 //at conditional request the image states are set when reaching the reset state
561 oFsm.conditionalCancelRequested = true
562 err = aPAFsm.pFsm.Event(upgradeEvReset) //as state-conditional default FSM cleanup
563 }
564 if err != nil {
565 //error return is expected in case of conditional request and no state transition
566 logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
567 "device-id": oFsm.deviceID, "error": err})
568 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000569 } //else the FSM seems already to be in some released state
570 }(pAdaptFsm)
571 }
572}
573
mpagenko80622a52021-02-09 16:53:23 +0000574func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
575 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
576 "device-id": oFsm.deviceID})
577
578 // start go routine for processing of LockState messages
579 go oFsm.processOmciUpgradeMessages(ctx)
580}
581
mpagenkoc26d4c02021-05-06 14:27:57 +0000582//enterWaitingAdapterDL state can only be reached with useAPIVersion43
583func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
584 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
585 "device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +0000586 syncChannel := make(chan struct{})
587 go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
588 //block until the wait routine is really blocked on chAdapterDlReady
589 <-syncChannel
mpagenkoc26d4c02021-05-06 14:27:57 +0000590 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
591}
592
mpagenko80622a52021-02-09 16:53:23 +0000593func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
594 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
595 "device-id": oFsm.deviceID})
596
mpagenkoc26d4c02021-05-06 14:27:57 +0000597 var fileLen int64
598 var err error
mpagenkoaa3afe92021-05-21 16:20:58 +0000599 oFsm.mutexUpgradeParams.Lock()
mpagenkoc26d4c02021-05-06 14:27:57 +0000600 if oFsm.useAPIVersion43 {
601 //with the new API structure download to adapter is implicit and we have to wait until the image is available
602 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
603 } else {
604 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
605 }
mpagenko80622a52021-02-09 16:53:23 +0000606 if err != nil || fileLen > int64(cMaxUint32) {
mpagenko38662d02021-08-11 09:45:19 +0000607 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000608 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenko38662d02021-08-11 09:45:19 +0000609 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
mpagenkoaa3afe92021-05-21 16:20:58 +0000610 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000611 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
612 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
613 pBaseFsm := oFsm.pAdaptFsm
614 // Can't call FSM Event directly, decoupling it
615 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000616 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000617 }(pBaseFsm)
618 return
619 }
620
mpagenkoc26d4c02021-05-06 14:27:57 +0000621 //copy file content to buffer
mpagenko80622a52021-02-09 16:53:23 +0000622 oFsm.imageBuffer = make([]byte, fileLen)
mpagenkoc26d4c02021-05-06 14:27:57 +0000623 if oFsm.useAPIVersion43 {
624 oFsm.imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
625 } else {
626 oFsm.imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
627 }
mpagenko80622a52021-02-09 16:53:23 +0000628 if err != nil {
mpagenko38662d02021-08-11 09:45:19 +0000629 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000630 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenko38662d02021-08-11 09:45:19 +0000631 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
mpagenkoaa3afe92021-05-21 16:20:58 +0000632 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000633 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
634 "device-id": oFsm.deviceID, "error": err})
635 pBaseFsm := oFsm.pAdaptFsm
636 // Can't call FSM Event directly, decoupling it
637 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000638 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000639 }(pBaseFsm)
640 return
641 }
642
643 oFsm.noOfSections = uint32(fileLen / cOmciDownloadSectionSize)
644 if fileLen%cOmciDownloadSectionSize > 0 {
mpagenkoc26d4c02021-05-06 14:27:57 +0000645 bufferPadding := make([]byte, cOmciDownloadSectionSize-uint32((fileLen)%cOmciDownloadSectionSize))
mpagenko80622a52021-02-09 16:53:23 +0000646 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
mpagenkoc26d4c02021-05-06 14:27:57 +0000647 oFsm.imageBuffer = append(oFsm.imageBuffer[:(fileLen)], bufferPadding...)
mpagenko80622a52021-02-09 16:53:23 +0000648 oFsm.noOfSections++
649 }
650 oFsm.origImageLength = uint32(fileLen)
651 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000652 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
653 "MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
654 "ImageSize": oFsm.imageLength, "original file size": fileLen})
655 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
mpagenkoaa3afe92021-05-21 16:20:58 +0000656
657 oFsm.mutexUpgradeParams.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +0000658
659 // flush commMetricsChan
660 select {
661 case <-oFsm.chOnuDlReady:
662 logger.Debug(ctx, "flushed OnuDlReady channel")
663 default:
664 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000665 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
666
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000667 err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000668 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
669 if err != nil {
670 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
671 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000672 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000673 return
674 }
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000675 oFsm.isEndSwDlOpen = true
mpagenko80622a52021-02-09 16:53:23 +0000676}
677
678func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
679 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
680 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
681
682 var windowAckRequest uint8 = 0
683 var bufferStartOffset uint32
684 var bufferEndOffset uint32
685 var downloadSection []byte
686 framePrint := false //default no printing of downloadSection frames
mpagenkoaa3afe92021-05-21 16:20:58 +0000687 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000688 if oFsm.nextDownloadSectionsAbsolute == 0 {
689 //debug print of first section frame
690 framePrint = true
mpagenkoaa3afe92021-05-21 16:20:58 +0000691 oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
mpagenko80622a52021-02-09 16:53:23 +0000692 }
693
694 for {
mpagenko38662d02021-08-11 09:45:19 +0000695 oFsm.mutexAbortRequest.RLock()
696 // this way out of the section download loop on abort request
697 if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
698 if oFsm.abortRequested == voltha.ImageState_CANCELLED_ON_REQUEST {
699 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
700 } else {
701 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
702 }
703 oFsm.volthaDownloadReason = oFsm.abortRequested
704 oFsm.mutexAbortRequest.RUnlock()
705 oFsm.mutexUpgradeParams.Unlock()
706 pBaseFsm := oFsm.pAdaptFsm
707 // Can't call FSM Event directly, decoupling it
708 go func(a_pAFsm *AdapterFsm) {
709 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
710 }(pBaseFsm)
711 return
712 }
713 oFsm.mutexAbortRequest.RUnlock()
714
mpagenko80622a52021-02-09 16:53:23 +0000715 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
716 bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
717 logger.Debugw(ctx, "DlSection values are", log.Fields{
718 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
719 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
720 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
721 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
722 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
723 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
724 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
mpagenko38662d02021-08-11 09:45:19 +0000725 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000726 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'LOCAL_FILE_ERROR' would be better (proto)
mpagenkoaa3afe92021-05-21 16:20:58 +0000727 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000728 //logical error -- reset the FSM
729 pBaseFsm := oFsm.pAdaptFsm
730 // Can't call FSM Event directly, decoupling it
731 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000732 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000733 }(pBaseFsm)
734 return
735 }
736 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
737 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
738 windowAckRequest = 1
739 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
740 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
741 }
742 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
743 windowAckRequest = 1
744 framePrint = true //debug print of last frame
mpagenko15ff4a52021-03-02 10:09:20 +0000745 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
746 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000747 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
748 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000749 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000750 err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000751 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
752 if err != nil {
753 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000754 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000755 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000756 return
757 }
mpagenkoaa3afe92021-05-21 16:20:58 +0000758 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000759 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
760 if windowAckRequest == 1 {
761 pBaseFsm := oFsm.pAdaptFsm
762 // Can't call FSM Event directly, decoupling it
mpagenkoaa3afe92021-05-21 16:20:58 +0000763 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000764 go func(a_pAFsm *AdapterFsm) {
765 _ = a_pAFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
766 }(pBaseFsm)
767 return
768 }
769 framePrint = false //for the next Section frame (if wanted, can be enabled in logic before sendXXX())
770 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000771 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000772 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenkoaa3afe92021-05-21 16:20:58 +0000773 oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
mpagenko59498c12021-03-18 14:15:15 +0000774 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenkoaa3afe92021-05-21 16:20:58 +0000775 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +0000776 }
777 }
778}
779
780func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
781 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
782 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
783}
784
785func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000786 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000787 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
mpagenko80622a52021-02-09 16:53:23 +0000788
mpagenkoaa3afe92021-05-21 16:20:58 +0000789 oFsm.mutexUpgradeParams.RLock()
mpagenko80622a52021-02-09 16:53:23 +0000790 if oFsm.delayEndSwDl {
mpagenkoaa3afe92021-05-21 16:20:58 +0000791 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000792 //give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
793 // should not be set in case this state is used for real download abort (not yet implemented)
794 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
mpagenkoaa3afe92021-05-21 16:20:58 +0000795 } else {
796 oFsm.mutexUpgradeParams.RUnlock()
mpagenko80622a52021-02-09 16:53:23 +0000797 }
798
mpagenko59498c12021-03-18 14:15:15 +0000799 pBaseFsm := oFsm.pAdaptFsm
800 if pBaseFsm == nil {
mpagenko38662d02021-08-11 09:45:19 +0000801 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
802 oFsm.mutexUpgradeParams.Lock()
803 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
804 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
805 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000806 // Can't call FSM Event directly, decoupling it
807 go func(a_pAFsm *AdapterFsm) {
808 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
809 }(pBaseFsm)
810 return
811 }
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000812 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko59498c12021-03-18 14:15:15 +0000813 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.origImageLength, oFsm.imageCRC)
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000814
815 oFsm.isEndSwDlOpen = false // also to be reset in case of OMCI error, as further send attempts would not make sense
mpagenko80622a52021-02-09 16:53:23 +0000816 if err != nil {
817 logger.Errorw(ctx, "EndSwDl abort: can't send section", log.Fields{
818 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000819 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +0000820 return
821 }
mpagenko59498c12021-03-18 14:15:15 +0000822 // go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
823 // Can't call FSM Event directly, decoupling it
824 go func(a_pAFsm *AdapterFsm) {
825 _ = a_pAFsm.pFsm.Event(upgradeEvWaitEndDownload)
826 }(pBaseFsm)
827}
828
829func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
830 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
831 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
832 if oFsm.waitCountEndSwDl == 0 {
833 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
834 "device-id": oFsm.deviceID})
835 pBaseFsm := oFsm.pAdaptFsm
836 if pBaseFsm == nil {
837 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
838 "device-id": oFsm.deviceID})
839 return
840 }
mpagenko38662d02021-08-11 09:45:19 +0000841 oFsm.mutexUpgradeParams.Lock()
842 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
mpagenko39b703e2021-08-25 13:38:40 +0000843 oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
mpagenko38662d02021-08-11 09:45:19 +0000844 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000845 go func(a_pAFsm *AdapterFsm) {
846 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
847 }(pBaseFsm)
848 return
849 }
850
851 oFsm.waitCountEndSwDl--
852 select {
853 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
854 pBaseFsm := oFsm.pAdaptFsm
855 if pBaseFsm == nil {
856 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
857 "device-id": oFsm.deviceID})
858 //FSM may be reset already from somewhere else, nothing we can do here anymore
859 return
860 }
861 //retry End SW DL
mpagenkoaa3afe92021-05-21 16:20:58 +0000862 oFsm.mutexUpgradeParams.Lock()
mpagenko59498c12021-03-18 14:15:15 +0000863 oFsm.delayEndSwDl = false //no more extra delay for the request
mpagenkoaa3afe92021-05-21 16:20:58 +0000864 oFsm.mutexUpgradeParams.Unlock()
mpagenko59498c12021-03-18 14:15:15 +0000865 go func(a_pAFsm *AdapterFsm) {
866 _ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
867 }(pBaseFsm)
868 return
869 case success := <-oFsm.chReceiveExpectedResponse:
870 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
871 pBaseFsm := oFsm.pAdaptFsm
872 if pBaseFsm == nil {
873 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
874 "device-id": oFsm.deviceID})
875 //FSM may be reset already from somewhere else, nothing we can do here anymore
876 return
877 }
878 if success {
879 //answer received with ready indication
mpagenko38662d02021-08-11 09:45:19 +0000880 //useAPIVersion43 may not conflict in concurrency in this state function
881 if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
mpagenkoc26d4c02021-05-06 14:27:57 +0000882 go func(a_pAFsm *AdapterFsm) {
mpagenko38662d02021-08-11 09:45:19 +0000883 _ = a_pAFsm.pFsm.Event(upgradeEvCheckImageName)
mpagenkoc26d4c02021-05-06 14:27:57 +0000884 }(pBaseFsm)
mpagenko38662d02021-08-11 09:45:19 +0000885 } else { // elder API usage does not support image version check -immediately consider download as successful
886 if oFsm.activateImage {
887 //immediate activation requested
888 go func(a_pAFsm *AdapterFsm) {
889 _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
890 }(pBaseFsm)
891 } else {
892 //have to wait on explicit activation request
893 go func(a_pAFsm *AdapterFsm) {
894 _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
895 }(pBaseFsm)
896 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000897 }
mpagenko59498c12021-03-18 14:15:15 +0000898 return
899 }
900 //timer was aborted
mpagenko38662d02021-08-11 09:45:19 +0000901 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko59498c12021-03-18 14:15:15 +0000902 return
903 }
mpagenko80622a52021-02-09 16:53:23 +0000904}
905
mpagenko38662d02021-08-11 09:45:19 +0000906func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
907 logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
908 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
909 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000910 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
mpagenko38662d02021-08-11 09:45:19 +0000911 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
912 false, oFsm.pAdaptFsm.commChan)
913 if err != nil {
914 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
915 log.Fields{"device-id": oFsm.deviceID, "Error": err})
916 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
917 return
918 }
919 oFsm.pLastTxMeInstance = meInstance
920}
921
mpagenko80622a52021-02-09 16:53:23 +0000922func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
923 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
924 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
925
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000926 err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000927 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
928 if err != nil {
929 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
930 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000931 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +0000932 return
933 }
mpagenko38662d02021-08-11 09:45:19 +0000934 oFsm.mutexUpgradeParams.Lock()
935 oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
936 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +0000937}
938
939func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +0000940 logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
941 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
942 //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
943 // (which is a bit problematic as the ONU might already be in committed state,
944 // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
945 if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
mpagenkoaa3afe92021-05-21 16:20:58 +0000946 oFsm.mutexUpgradeParams.Lock()
mpagenko38662d02021-08-11 09:45:19 +0000947 if activeImageID == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +0000948 inactiveImageID := oFsm.inactiveImageMeID
mpagenko15ff4a52021-03-02 10:09:20 +0000949 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
mpagenkoaa3afe92021-05-21 16:20:58 +0000950 "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
951 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
952 oFsm.mutexUpgradeParams.Unlock()
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000953 err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenkoaa3afe92021-05-21 16:20:58 +0000954 oFsm.pAdaptFsm.commChan, inactiveImageID) //more efficient activeImageID with above check
mpagenko15ff4a52021-03-02 10:09:20 +0000955 if err != nil {
956 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
957 "device-id": oFsm.deviceID, "error": err})
mpagenko38662d02021-08-11 09:45:19 +0000958 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +0000959 return
960 }
961 return
962 }
mpagenko38662d02021-08-11 09:45:19 +0000963 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000964 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
965 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
mpagenko38662d02021-08-11 09:45:19 +0000966 } else {
967 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
968 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000969 }
mpagenko38662d02021-08-11 09:45:19 +0000970 oFsm.mutexUpgradeParams.Lock()
971 oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
972 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
973 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
974 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
975 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +0000976 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
977 pBaseFsm := oFsm.pAdaptFsm
978 // Can't call FSM Event directly, decoupling it
979 go func(a_pAFsm *AdapterFsm) {
980 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
981 }(pBaseFsm)
982}
983
984func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
mpagenko38662d02021-08-11 09:45:19 +0000985 logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000986 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
mpagenko15ff4a52021-03-02 10:09:20 +0000987 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
Holger Hildebrandt288d9472021-09-06 10:47:53 +0000988 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra0b235842021-03-09 13:06:46 -0800989 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300990 if err != nil {
991 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
992 log.Fields{"device-id": oFsm.deviceID, "Error": err})
mpagenko38662d02021-08-11 09:45:19 +0000993 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300994 return
995 }
mpagenko15ff4a52021-03-02 10:09:20 +0000996 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +0000997}
998
999func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1000 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
1001
mpagenko38662d02021-08-11 09:45:19 +00001002 // if the reset was conditionally requested
1003 if oFsm.conditionalCancelRequested {
1004 oFsm.mutexUpgradeParams.Lock()
1005 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1006 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1007 oFsm.mutexUpgradeParams.Unlock()
1008 }
1009
mpagenkoc26d4c02021-05-06 14:27:57 +00001010 // in case the download-to-ONU timer is still running - cancel it
mpagenko39b703e2021-08-25 13:38:40 +00001011 //use non-blocking channel (to be independent from receiver state)
1012 select {
1013 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1014 case oFsm.chOnuDlReady <- false:
1015 default:
mpagenkoc26d4c02021-05-06 14:27:57 +00001016 }
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001017 pConfigupgradeStateAFsm := oFsm.pAdaptFsm
1018 if pConfigupgradeStateAFsm != nil {
1019 var nextEvent string
1020 if oFsm.isEndSwDlOpen {
1021 nextEvent = upgradeEvAbortSwDownload
1022 } else {
1023 nextEvent = upgradeEvRestart
1024 }
1025 // Can't call FSM Event directly, decoupling it
1026 go func(a_pAFsm *AdapterFsm) {
1027 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1028 _ = a_pAFsm.pFsm.Event(nextEvent)
1029 }
1030 }(pConfigupgradeStateAFsm)
1031 }
1032}
mpagenkoc26d4c02021-05-06 14:27:57 +00001033
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001034func (oFsm *OnuUpgradeFsm) enterAbortingDL(ctx context.Context, e *fsm.Event) {
1035 logger.Debugw(ctx, "OnuUpgradeFsm aborting download to ONU", log.Fields{"device-id": oFsm.deviceID})
1036
1037 pBaseFsm := oFsm.pAdaptFsm
1038 if pBaseFsm == nil {
1039 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
1040 return
1041 }
1042 // abort the download operation by sending an end software download message with invalid CRC and image size
1043 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.Background(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
1044 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, 0, 0xFFFFFFFF)
1045
1046 oFsm.isEndSwDlOpen = false // also to be reset in case of OMCI error, as further send attempts would not make sense
1047
1048 if err != nil {
1049 logger.Errorw(ctx, "OnuUpgradeFsm aborting download: can't send EndSwDl request", log.Fields{"device-id": oFsm.deviceID})
1050 // Can't call FSM Event directly, decoupling it
1051 go func(a_pAFsm *AdapterFsm) {
1052 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1053 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1054 }
1055 }(pBaseFsm)
1056 return
1057 }
1058 select {
1059 case <-time.After(oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second):
1060 logger.Warnw(ctx, "OnuUpgradeFsm aborting download: timeout - no response received", log.Fields{"device-id": oFsm.deviceID})
1061 go func(a_pAFsm *AdapterFsm) {
1062 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1063 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1064 }
1065 }(pBaseFsm)
1066 return
1067 case <-oFsm.chReceiveAbortEndSwDlResponse:
1068 logger.Debug(ctx, "OnuUpgradeFsm aborting download: response received")
1069 go func(a_pAFsm *AdapterFsm) {
1070 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
1071 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
1072 }
1073 }(pBaseFsm)
1074 return
1075 }
1076}
1077
1078func (oFsm *OnuUpgradeFsm) enterRestarting(ctx context.Context, e *fsm.Event) {
1079 logger.Debugw(ctx, "OnuUpgradeFsm restarting", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +00001080 pConfigupgradeStateAFsm := oFsm.pAdaptFsm
1081 if pConfigupgradeStateAFsm != nil {
1082 // abort running message processing
1083 fsmAbortMsg := Message{
1084 Type: TestMsg,
1085 Data: TestMessage{
1086 TestMessageVal: AbortMessageProcessing,
1087 },
1088 }
1089 pConfigupgradeStateAFsm.commChan <- fsmAbortMsg
1090
1091 //try to restart the FSM to 'disabled'
1092 // Can't call FSM Event directly, decoupling it
1093 go func(a_pAFsm *AdapterFsm) {
1094 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001095 _ = a_pAFsm.pFsm.Event(upgradeEvDisable)
mpagenko80622a52021-02-09 16:53:23 +00001096 }
1097 }(pConfigupgradeStateAFsm)
1098 }
1099}
1100
1101func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1102 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001103 // 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 +00001104 if oFsm.pDeviceHandler != nil {
1105 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenko38662d02021-08-11 09:45:19 +00001106 pLastUpgradeImageState := &voltha.ImageState{
1107 Version: oFsm.imageVersion,
1108 DownloadState: oFsm.volthaDownloadState,
1109 Reason: oFsm.volthaDownloadReason,
1110 ImageState: oFsm.volthaImageState,
1111 }
1112 go oFsm.pDeviceHandler.removeOnuUpgradeFsm(ctx, pLastUpgradeImageState)
mpagenko80622a52021-02-09 16:53:23 +00001113 }
1114}
1115
1116func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
1117 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
1118loop:
1119 for {
1120 // case <-ctx.Done():
1121 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
1122 // break loop
1123 message, ok := <-oFsm.pAdaptFsm.commChan
1124 if !ok {
1125 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
1126 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko38662d02021-08-11 09:45:19 +00001127 oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenko80622a52021-02-09 16:53:23 +00001128 break loop
1129 }
1130 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
1131
1132 switch message.Type {
1133 case TestMsg:
1134 msg, _ := message.Data.(TestMessage)
1135 if msg.TestMessageVal == AbortMessageProcessing {
1136 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
1137 break loop
1138 }
1139 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
1140 case OMCI:
1141 msg, _ := message.Data.(OmciMessage)
1142 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
1143 default:
1144 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
1145 "message.Type": message.Type})
1146 }
1147 }
1148 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
1149}
1150
1151//nolint: gocyclo
1152func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg OmciMessage) {
1153 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
1154 "msgType": msg.OmciMsg.MessageType})
1155
1156 switch msg.OmciMsg.MessageType {
1157 case omci.StartSoftwareDownloadResponseType:
1158 {
1159 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
1160 if msgLayer == nil {
1161 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
1162 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001163 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001164 return
1165 }
1166 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
1167 if !msgOk {
1168 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
1169 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001170 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001171 return
1172 }
1173 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
1174 "device-id": oFsm.deviceID, "data-fields": msgObj})
1175 if msgObj.Result != me.Success {
1176 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
1177 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001178 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001179 return
1180 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001181
1182 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001183 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1184 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1185 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
1186 // also response WindowSize = 0 is a valid number for used Window size 1
1187 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
1188 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
1189 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
1190 }
1191 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
1192 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
1193 oFsm.noOfWindows++
1194 }
1195 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
1196 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
1197 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
1198 oFsm.nextDownloadSectionsAbsolute = 0
1199 oFsm.nextDownloadSectionsWindow = 0
1200 oFsm.nextDownloadWindow = 0
1201
mpagenkoaa3afe92021-05-21 16:20:58 +00001202 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001203 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
1204 return
1205 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001206 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001207 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1208 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001209 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001210 return
1211 } //StartSoftwareDownloadResponseType
1212 case omci.DownloadSectionResponseType:
1213 {
mpagenko80622a52021-02-09 16:53:23 +00001214 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
1215 if msgLayer == nil {
1216 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
1217 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
mpagenko38662d02021-08-11 09:45:19 +00001218 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001219 return
1220 }
1221 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
1222 if !msgOk {
1223 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
1224 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001225 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001226 return
1227 }
1228 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
1229 "device-id": oFsm.deviceID, "data-fields": msgObj})
1230 if msgObj.Result != me.Success {
1231 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
1232 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001233 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001234 return
1235 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001236 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001237 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1238 sectionNumber := msgObj.SectionNumber
mpagenko15ff4a52021-03-02 10:09:20 +00001239 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
1240 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +00001241
mpagenko15ff4a52021-03-02 10:09:20 +00001242 oFsm.nextDownloadWindow++
1243 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
1244 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
mpagenko02cf1b22021-03-12 17:30:30 +00001245 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
mpagenko15ff4a52021-03-02 10:09:20 +00001246 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
1247 "expected section": oFsm.omciDownloadWindowSizeLast})
mpagenkoaa3afe92021-05-21 16:20:58 +00001248 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001249 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko15ff4a52021-03-02 10:09:20 +00001250 return
1251 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001252 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
1253 //CRC computation for all data bytes of the file
1254 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
1255 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
1256 var byteSlice []byte = make([]byte, 4)
1257 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
1258 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
mpagenkoaa3afe92021-05-21 16:20:58 +00001259 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001260 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
1261 return
1262 }
1263 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
1264 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
mpagenko02cf1b22021-03-12 17:30:30 +00001265 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
1266 "expected section": oFsm.omciDownloadWindowSizeLimit})
mpagenkoaa3afe92021-05-21 16:20:58 +00001267 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001268 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko15ff4a52021-03-02 10:09:20 +00001269 return
1270 }
1271 oFsm.nextDownloadSectionsWindow = 0
mpagenkoaa3afe92021-05-21 16:20:58 +00001272 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001273 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
mpagenko80622a52021-02-09 16:53:23 +00001274 return
1275 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001276 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001277 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1278 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001279 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001280 return
mpagenko80622a52021-02-09 16:53:23 +00001281 } //DownloadSectionResponseType
1282 case omci.EndSoftwareDownloadResponseType:
1283 {
Holger Hildebrandt288d9472021-09-06 10:47:53 +00001284 if oFsm.pAdaptFsm.pFsm.Is(upgradeStAbortingDL) {
1285 // calling FSM events in background to avoid blocking of the caller
1286 go func(aPAFsm *AdapterFsm) {
1287 oFsm.chReceiveAbortEndSwDlResponse <- true
1288 }(oFsm.pAdaptFsm)
1289 return
1290 }
mpagenko80622a52021-02-09 16:53:23 +00001291 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1292 if msgLayer == nil {
1293 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1294 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001295 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001296 return
1297 }
1298 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1299 if !msgOk {
1300 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1301 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001302 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001303 return
1304 }
1305 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1306 "device-id": oFsm.deviceID, "data-fields": msgObj})
1307 if msgObj.Result != me.Success {
mpagenko59498c12021-03-18 14:15:15 +00001308 if msgObj.Result == me.DeviceBusy {
1309 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1310 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1311 "device-id": oFsm.deviceID})
1312 return
1313 }
mpagenko80622a52021-02-09 16:53:23 +00001314 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
1315 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001316 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001317 return
1318 }
mpagenko183647c2021-06-08 15:25:04 +00001319 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001320 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko38662d02021-08-11 09:45:19 +00001321 //EndSwDownloadSuccess is used to indicate 'DOWNLOAD_SUCCEEDED'
mpagenko183647c2021-06-08 15:25:04 +00001322 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
mpagenko38662d02021-08-11 09:45:19 +00001323 if !oFsm.useAPIVersion43 {
1324 //in the older API version the image version check was not possible
1325 // - assume new loaded image as valid-inactive immediately
1326 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1327 oFsm.mutexUpgradeParams.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +00001328 //use non-blocking channel (to be independent from receiver state)
1329 select {
1330 //use non-blocking channel to indicate that the download to ONU was successful
1331 case oFsm.chOnuDlReady <- true:
1332 default:
mpagenko38662d02021-08-11 09:45:19 +00001333 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001334 } else {
mpagenko38662d02021-08-11 09:45:19 +00001335 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001336 }
mpagenko38662d02021-08-11 09:45:19 +00001337 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
1338 //use non-blocking channel to let the FSM proceed from the waitState
1339 select {
1340 case oFsm.chReceiveExpectedResponse <- true:
1341 default:
1342 }
mpagenko80622a52021-02-09 16:53:23 +00001343 return
1344 }
mpagenko183647c2021-06-08 15:25:04 +00001345 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001346 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1347 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001348 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
mpagenko80622a52021-02-09 16:53:23 +00001349 return
1350 } //EndSoftwareDownloadResponseType
1351 case omci.ActivateSoftwareResponseType:
1352 {
1353 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1354 if msgLayer == nil {
1355 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1356 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001357 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001358 return
1359 }
1360 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1361 if !msgOk {
1362 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1363 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001364 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001365 return
1366 }
1367 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1368 "device-id": oFsm.deviceID, "data-fields": msgObj})
1369 if msgObj.Result != me.Success {
1370 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1371 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001372 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001373 return
1374 }
mpagenko183647c2021-06-08 15:25:04 +00001375 oFsm.mutexUpgradeParams.Lock()
mpagenko80622a52021-02-09 16:53:23 +00001376 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko38662d02021-08-11 09:45:19 +00001377 // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
mpagenko183647c2021-06-08 15:25:04 +00001378 oFsm.mutexUpgradeParams.Unlock()
1379 logger.Infow(ctx, "Expected ActivateSwResponse received",
1380 log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
1381 if oFsm.commitImage {
1382 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
1383 } else {
1384 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvActivationDone) // let the FSM wait for external commit request
1385 }
mpagenko80622a52021-02-09 16:53:23 +00001386 return
1387 }
mpagenko183647c2021-06-08 15:25:04 +00001388 oFsm.mutexUpgradeParams.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001389 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1390 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001391 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
mpagenko80622a52021-02-09 16:53:23 +00001392 return
1393 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001394 case omci.CommitSoftwareResponseType:
1395 {
1396 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1397 if msgLayer == nil {
1398 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1399 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001400 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001401 return
1402 }
1403 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1404 if !msgOk {
1405 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1406 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001407 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001408 return
1409 }
mpagenkobf67a092021-03-17 09:52:28 +00001410 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001411 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1412 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001413 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001414 return
mpagenkobf67a092021-03-17 09:52:28 +00001415 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001416 oFsm.mutexUpgradeParams.RLock()
mpagenko15ff4a52021-03-02 10:09:20 +00001417 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenkoaa3afe92021-05-21 16:20:58 +00001418 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001419 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1420 //verifying committed image
1421 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
1422 return
1423 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001424 oFsm.mutexUpgradeParams.RUnlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001425 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1426 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko38662d02021-08-11 09:45:19 +00001427 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001428 return
1429 } //CommitSoftwareResponseType
1430 case omci.GetResponseType:
1431 {
1432 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1433 if msgLayer == nil {
1434 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1435 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001436 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001437 return
1438 }
1439 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1440 if !msgOk {
1441 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1442 log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001443 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001444 return
1445 }
1446 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1447 "device-id": oFsm.deviceID, "data-fields": msgObj})
1448 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1449 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1450 if msgObj.Result != me.Success {
1451 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1452 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko38662d02021-08-11 09:45:19 +00001453 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
mpagenko15ff4a52021-03-02 10:09:20 +00001454 return
1455 }
1456 } else {
1457 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1458 log.Fields{"device-id": oFsm.deviceID})
1459 return
1460 }
1461
1462 meAttributes := msgObj.Attributes
1463 imageIsCommitted := meAttributes["IsCommitted"].(uint8)
1464 imageIsActive := meAttributes["IsActive"].(uint8)
Holger Hildebrandtfb402a62021-05-26 14:40:49 +00001465 imageVersion := TrimStringFromMeOctet(meAttributes["Version"])
mpagenko02cf1b22021-03-12 17:30:30 +00001466 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
mpagenko15ff4a52021-03-02 10:09:20 +00001467 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1468 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
mpagenkoaa3afe92021-05-21 16:20:58 +00001469
mpagenko38662d02021-08-11 09:45:19 +00001470 if oFsm.pAdaptFsm.pFsm.Current() == upgradeStCheckImageName {
1471 //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
1472 oFsm.mutexUpgradeParams.Lock()
1473 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsInactive &&
1474 imageIsCommitted == swIsUncommitted {
1475 if imageVersion != oFsm.imageVersion {
1476 //new stored inactive version indicated on OMCI from ONU is not the expected version
1477 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
1478 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1479 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1480 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was downloaded
1481 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1482 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'DOWNLOADED' would be better - proto def
1483 oFsm.mutexUpgradeParams.Unlock()
1484 //stop the running ONU download timer
mpagenko39b703e2021-08-25 13:38:40 +00001485 //use non-blocking channel (to be independent from receiver state)
1486 select {
1487 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
1488 case oFsm.chOnuDlReady <- false:
1489 default:
mpagenko38662d02021-08-11 09:45:19 +00001490 }
1491 // TODO!!!: error treatment?
1492 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1493 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1494 return
1495 }
1496 //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
1497 oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
1498 //store the new inactive version to onuSwImageIndications (to keep them in sync)
1499 oFsm.pDevEntry.modifySwImageInactiveVersion(ctx, oFsm.imageVersion)
1500 //proceed within upgrade FSM
1501 if oFsm.activateImage {
1502 //immediate activation requested
1503 oFsm.mutexUpgradeParams.Unlock()
1504 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
1505 log.Fields{"device-id": oFsm.deviceID})
1506 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRequestActivate)
1507 } else {
1508 //have to wait on explicit activation request
1509 // but a previously requested download activity (without activation) was successful here
1510 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
1511 oFsm.mutexUpgradeParams.Unlock()
1512 logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
1513 log.Fields{"device-id": oFsm.deviceID})
1514 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForActivate)
1515 }
mpagenko39b703e2021-08-25 13:38:40 +00001516 //use non-blocking channel (to be independent from receiver state)
1517 select {
1518 //use non-blocking channel to indicate that the download to ONU was successful
1519 case oFsm.chOnuDlReady <- true:
1520 default:
mpagenko38662d02021-08-11 09:45:19 +00001521 }
1522 return
1523 }
1524 //not the expected image/image state
1525 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1526 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1527 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //real image state not known
1528 oFsm.mutexUpgradeParams.Unlock()
1529 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1530 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1531 // TODO!!!: error treatment?
1532 //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
1533 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1534 return
1535 }
1536
1537 //assumed only relevant state here is upgradeStCheckCommitted
mpagenkoaa3afe92021-05-21 16:20:58 +00001538 oFsm.mutexUpgradeParams.Lock()
mpagenko38662d02021-08-11 09:45:19 +00001539 oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
mpagenkoaa3afe92021-05-21 16:20:58 +00001540 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive {
mpagenkoc26d4c02021-05-06 14:27:57 +00001541 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1542 // indicated in the download image version string (version must be part of the image content itself)
1543 // so checking that might be quite unreliable
1544 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1545 // in all the API references, so it can and should be checked here now
1546 if oFsm.useAPIVersion43 {
1547 if imageVersion != oFsm.imageVersion {
1548 //new active version indicated on OMCI from ONU is not the expected version
mpagenko38662d02021-08-11 09:45:19 +00001549 logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
mpagenkoc26d4c02021-05-06 14:27:57 +00001550 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1551 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1552 // TODO!!!: error treatment?
mpagenko38662d02021-08-11 09:45:19 +00001553 //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
1554 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was committed
1555 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
1556 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //expected image not known
1557 oFsm.mutexUpgradeParams.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001558 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1559 return
1560 }
1561 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1562 log.Fields{"device-id": oFsm.deviceID})
1563 }
mpagenkoaa3afe92021-05-21 16:20:58 +00001564 if imageIsCommitted == swIsCommitted {
mpagenko38662d02021-08-11 09:45:19 +00001565 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
mpagenkoaa3afe92021-05-21 16:20:58 +00001566 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
mpagenko38662d02021-08-11 09:45:19 +00001567 //store the new commit flag to onuSwImageIndications (to keep them in sync)
1568 oFsm.pDevEntry.modifySwImageActiveCommit(ctx, imageIsCommitted)
mpagenkoaa3afe92021-05-21 16:20:58 +00001569 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
mpagenko38662d02021-08-11 09:45:19 +00001570 //deviceProcStatusUpdate not used anymore,
1571 // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
mpagenkoaa3afe92021-05-21 16:20:58 +00001572 oFsm.mutexUpgradeParams.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001573 //releasing the upgrade FSM on success
mpagenko183647c2021-06-08 15:25:04 +00001574 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenkoaa3afe92021-05-21 16:20:58 +00001575 return
1576 }
mpagenko38662d02021-08-11 09:45:19 +00001577 //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
mpagenko15ff4a52021-03-02 10:09:20 +00001578 }
mpagenko38662d02021-08-11 09:45:19 +00001579 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1580 oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
1581 oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
mpagenkoaa3afe92021-05-21 16:20:58 +00001582 oFsm.mutexUpgradeParams.Unlock()
mpagenko15ff4a52021-03-02 10:09:20 +00001583 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1584 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1585 // TODO!!!: error treatment?
1586 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1587 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1588 return
1589 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001590 default:
1591 {
1592 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1593 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1594 return
1595 }
1596 }
1597}
1598
mpagenko38662d02021-08-11 09:45:19 +00001599//abortOnOmciError aborts the upgrade processing with OMCI_TRANSFER_ERROR indication
1600func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool,
1601 aImageState voltha.ImageState_ImageActivationState) {
1602 oFsm.mutexUpgradeParams.Lock()
1603 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1604 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1605 oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
1606 if aImageState != voltha.ImageState_IMAGE_UNKNOWN {
1607 // update image state only in case some explicite state is given (otherwise the existing state is used)
1608 oFsm.volthaImageState = aImageState
1609 }
1610 oFsm.mutexUpgradeParams.Unlock()
1611 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1612 if oFsm.pAdaptFsm != nil {
1613 var err error
1614 if aAsync { //asynchronous call requested to ensure state transition
1615 go func(a_pAFsm *AdapterFsm) {
1616 if a_pAFsm.pFsm != nil {
1617 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1618 }
1619 }(oFsm.pAdaptFsm)
1620 } else {
1621 if oFsm.pAdaptFsm.pFsm != nil {
1622 err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1623 }
1624 }
1625 if err != nil {
1626 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1627 "device-id": oFsm.deviceID, "error": err})
1628 }
1629 }
1630}
1631
mpagenkoc26d4c02021-05-06 14:27:57 +00001632//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
mpagenko38662d02021-08-11 09:45:19 +00001633// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
1634func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
1635 aWaitChannel chan bool) {
mpagenkoc26d4c02021-05-06 14:27:57 +00001636 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
mpagenko38662d02021-08-11 09:45:19 +00001637 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
mpagenkoc26d4c02021-05-06 14:27:57 +00001638 oFsm.isWaitingForAdapterDlResponse = true
1639 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko38662d02021-08-11 09:45:19 +00001640 aSyncChannel <- struct{}{}
mpagenko80622a52021-02-09 16:53:23 +00001641 select {
1642 // maybe be also some outside cancel (but no context modeled for the moment ...)
1643 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001644 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1645 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1646 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1647 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1648 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
mpagenko39b703e2021-08-25 13:38:40 +00001649 //running into timeout here may still have the download to adapter active -> abort
1650 oFsm.pFileManager.CancelDownload(ctx, oFsm.imageIdentifier)
mpagenkoc26d4c02021-05-06 14:27:57 +00001651 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1652 oFsm.isWaitingForAdapterDlResponse = false
1653 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko39b703e2021-08-25 13:38:40 +00001654 oFsm.mutexUpgradeParams.Lock()
1655 oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
1656 oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
1657 oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //something like 'DOWNLOAD_TO_ADAPTER_TIMEOUT' would be better (proto)
1658 oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'IMAGE_DOWNLOAD_ABORTED' would be better (proto)
1659 oFsm.mutexUpgradeParams.Unlock()
1660 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1661 if oFsm.pAdaptFsm != nil && oFsm.pAdaptFsm.pFsm != nil {
1662 err := oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1663 if err != nil {
1664 logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
1665 "device-id": oFsm.deviceID, "error": err})
1666 }
1667 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001668 return
1669
1670 case success := <-aWaitChannel:
1671 if success {
1672 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1673 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1674 oFsm.isWaitingForAdapterDlResponse = false
1675 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1676 //let the upgrade process proceed
1677 pUpgradeFsm := oFsm.pAdaptFsm
1678 if pUpgradeFsm != nil {
1679 _ = pUpgradeFsm.pFsm.Event(upgradeEvPrepareSwDownload)
1680 } else {
1681 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1682 }
1683 return
1684 }
mpagenko39b703e2021-08-25 13:38:40 +00001685 // waiting was aborted (assumed here to be caused by
1686 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001687 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1688 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1689 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1690 oFsm.isWaitingForAdapterDlResponse = false
1691 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenkoc26d4c02021-05-06 14:27:57 +00001692 return
mpagenko80622a52021-02-09 16:53:23 +00001693 }
1694}
mpagenkoc26d4c02021-05-06 14:27:57 +00001695
1696//waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1697func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1698 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1699 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1700 "duration": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001701 select {
1702 // maybe be also some outside cancel (but no context modeled for the moment ...)
1703 // case <-ctx.Done():
1704 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1705 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1706 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1707 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
mpagenkoc26d4c02021-05-06 14:27:57 +00001708 //the upgrade process has to be aborted
mpagenko39b703e2021-08-25 13:38:40 +00001709 oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
mpagenkoc26d4c02021-05-06 14:27:57 +00001710 return
1711
1712 case success := <-aWaitChannel:
1713 if success {
1714 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001715 //all fine, let the FSM proceed like defined from the sender of this event
1716 return
1717 }
1718 // waiting was aborted (assumed here to be caused by
mpagenko39b703e2021-08-25 13:38:40 +00001719 // error detection or cancel at download after upgrade FSM reset/abort with according image states set there)
mpagenkoc26d4c02021-05-06 14:27:57 +00001720 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001721 return
1722 }
1723}