blob: 1e542ce7f39a810bae6088dc35528b28ba4d2bdb [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"
32 "github.com/opencord/voltha-lib-go/v4/pkg/log"
33 "github.com/opencord/voltha-protos/v4/go/voltha"
34)
35
36const cMaxUint32 = ^uint32(0)
37
38const (
39 // internal predefined values - some off them should later be configurable (perhaps with theses as defaults)
40 cOmciDownloadSectionSize = 31 //in bytes
41 cOmciDownloadWindowSizeLimit = 31 //in sections for window offset (windowSize(32)-1)
42 //cOmciDownloadWindowRetryMax = 2 // max attempts for a specific window
mpagenkoc26d4c02021-05-06 14:27:57 +000043 cOmciSectionInterleaveMilliseconds = 0 //DownloadSection interleave time in milliseconds (0 for no delay)
44 cOmciEndSwDlDelaySeconds = 1 //End Software Download delay after last section (may be also configurable?)
45 cWaitCountEndSwDl = 6 //maximum number of EndSwDl requests
46 cWaitDelayEndSwDlSeconds = 10 //duration, how long is waited before next request on EndSwDl
mpagenko80622a52021-02-09 16:53:23 +000047 //cOmciDownloadCompleteTimeout = 5400 //in s for the complete timeout (may be better scale to image size/ noOfWindows)
48)
49
50const (
51 // events of config PON ANI port FSM
52 upgradeEvStart = "upgradeEvStart"
mpagenkoc26d4c02021-05-06 14:27:57 +000053 upgradeEvAdapterDownload = "upgradeEvAdapterDownload"
mpagenko80622a52021-02-09 16:53:23 +000054 upgradeEvPrepareSwDownload = "upgradeEvPrepareSwDownload"
55 upgradeEvRxStartSwDownload = "upgradeEvRxStartSwDownload"
56 upgradeEvWaitWindowAck = "upgradeEvWaitWindowAck"
57 upgradeEvContinueNextWindow = "upgradeEvContinueNextWindow"
58 upgradeEvEndSwDownload = "upgradeEvEndSwDownload"
mpagenko59498c12021-03-18 14:15:15 +000059 upgradeEvWaitEndDownload = "upgradeEvWaitEndDownload"
60 upgradeEvContinueFinalize = "upgradeEvContinueFinalize"
mpagenkoc26d4c02021-05-06 14:27:57 +000061 upgradeEvWaitForActivate = "upgradeEvWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000062 upgradeEvRequestActivate = "upgradeEvRequestActivate"
63 upgradeEvWaitForCommit = "upgradeEvWaitForCommit"
64 upgradeEvCommitSw = "upgradeEvCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +000065 upgradeEvCheckCommitted = "upgradeEvCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +000066
67 //upgradeEvTimeoutSimple = "upgradeEvTimeoutSimple"
68 //upgradeEvTimeoutMids = "upgradeEvTimeoutMids"
69 upgradeEvReset = "upgradeEvReset"
70 upgradeEvAbort = "upgradeEvAbort"
71 upgradeEvRestart = "upgradeEvRestart"
72)
73
74const (
75 // states of config PON ANI port FSM
76 upgradeStDisabled = "upgradeStDisabled"
77 upgradeStStarting = "upgradeStStarting"
mpagenkoc26d4c02021-05-06 14:27:57 +000078 upgradeStWaitingAdapterDL = "upgradeStWaitingAdapterDL"
mpagenko80622a52021-02-09 16:53:23 +000079 upgradeStPreparingDL = "upgradeStPreparingDL"
80 upgradeStDLSection = "upgradeStDLSection"
81 upgradeStVerifyWindow = "upgradeStVerifyWindow"
82 upgradeStFinalizeDL = "upgradeStFinalizeDL"
mpagenko59498c12021-03-18 14:15:15 +000083 upgradeStWaitEndDL = "upgradeStWaitEndDL"
mpagenkoc26d4c02021-05-06 14:27:57 +000084 upgradeStWaitForActivate = "upgradeStWaitForActivate"
mpagenko80622a52021-02-09 16:53:23 +000085 upgradeStRequestingActivate = "upgradeStRequestingActivate"
86 upgradeStWaitForCommit = "upgradeStWaitForCommit"
87 upgradeStCommitSw = "upgradeStCommitSw"
mpagenko15ff4a52021-03-02 10:09:20 +000088 upgradeStCheckCommitted = "upgradeStCheckCommitted"
mpagenko80622a52021-02-09 16:53:23 +000089 upgradeStResetting = "upgradeStResetting"
90)
91
92//required definition for IdleState detection for activities on OMCI
93const cOnuUpgradeFsmIdleState = upgradeStWaitForCommit
94
95//OnuUpgradeFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
96type OnuUpgradeFsm struct {
97 pDeviceHandler *deviceHandler
98 pDownloadManager *adapterDownloadManager
mpagenkoc26d4c02021-05-06 14:27:57 +000099 pFileManager *fileDownloadManager //used from R2.8 with new API version
mpagenko80622a52021-02-09 16:53:23 +0000100 deviceID string
mpagenko15ff4a52021-03-02 10:09:20 +0000101 pOnuOmciDevice *OnuDeviceEntry
mpagenko80622a52021-02-09 16:53:23 +0000102 pOmciCC *omciCC
103 pOnuDB *onuDeviceDB
104 requestEvent OnuDeviceEvent
105 //omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
mpagenkoc26d4c02021-05-06 14:27:57 +0000106 pAdaptFsm *AdapterFsm
107 pImageDsc *voltha.ImageDownload
108 imageBuffer []byte
109 origImageLength uint32 //as also limited by OMCI
110 imageCRC uint32 //as per OMCI - ITU I.363.5 crc
111 imageLength uint32 //including last bytes padding
112 omciDownloadWindowSizeLimit uint8 //windowSize-1 in sections
113 omciDownloadWindowSizeLast uint8 //number of sections in last window
114 noOfSections uint32 //uint32 range for sections should be sufficient for very long images
115 nextDownloadSectionsAbsolute uint32 //number of next section to download in overall image
116 nextDownloadSectionsWindow uint8 //number of next section to download within current window
117 noOfWindows uint32 //uint32 range for windows should be sufficient for very long images
118 nextDownloadWindow uint32 //number of next window to download
119 inactiveImageMeID uint16 //ME-ID of the inactive image
120 downloadToOnuTimeout4MB time.Duration //timeout for downloading the image to the ONU for a 4MB image slice
121 omciSectionInterleaveDelay time.Duration //DownloadSectionInterleave delay in milliseconds
122 delayEndSwDl bool //flag to provide a delay between last section and EndSwDl
123 pLastTxMeInstance *me.ManagedEntity
124 waitCountEndSwDl uint8 //number, how often is waited for EndSwDl at maximum
125 waitDelayEndSwDl time.Duration //duration, how long is waited before next request on EndSwDl
126 chReceiveExpectedResponse chan bool
127 useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
128 mutexUpgradeParams sync.RWMutex
129 imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
130 imageIdentifier string //name of the image as used in the adapter
131 mutexIsAwaitingAdapterDlResponse sync.RWMutex
132 chAdapterDlReady chan bool
133 isWaitingForAdapterDlResponse bool
134 mutexIsAwaitingOnuDlResponse sync.RWMutex
135 chOnuDlReady chan bool
136 isWaitingForOnuDlResponse bool
137 activateImage bool
138 commitImage bool
mpagenko80622a52021-02-09 16:53:23 +0000139}
140
141//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
142// of ONU UNI ports via OMCI
143func NewOnuUpgradeFsm(ctx context.Context, apDeviceHandler *deviceHandler,
mpagenko15ff4a52021-03-02 10:09:20 +0000144 apDevEntry *OnuDeviceEntry, apOnuDB *onuDeviceDB,
mpagenko80622a52021-02-09 16:53:23 +0000145 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message) *OnuUpgradeFsm {
146 instFsm := &OnuUpgradeFsm{
mpagenko59498c12021-03-18 14:15:15 +0000147 pDeviceHandler: apDeviceHandler,
148 deviceID: apDeviceHandler.deviceID,
149 pOnuOmciDevice: apDevEntry,
150 pOmciCC: apDevEntry.PDevOmciCC,
151 pOnuDB: apOnuDB,
152 requestEvent: aRequestEvent,
153 omciDownloadWindowSizeLimit: cOmciDownloadWindowSizeLimit,
154 omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
155 waitCountEndSwDl: cWaitCountEndSwDl,
156 waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
mpagenko80622a52021-02-09 16:53:23 +0000157 }
mpagenko59498c12021-03-18 14:15:15 +0000158 instFsm.chReceiveExpectedResponse = make(chan bool)
mpagenkoc26d4c02021-05-06 14:27:57 +0000159 instFsm.chAdapterDlReady = make(chan bool)
160 instFsm.chOnuDlReady = make(chan bool)
mpagenko80622a52021-02-09 16:53:23 +0000161
162 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
163 if instFsm.pAdaptFsm == nil {
164 logger.Errorw(ctx, "OnuUpgradeFsm's AdapterFsm could not be instantiated!!", log.Fields{
165 "device-id": instFsm.deviceID})
166 return nil
167 }
168 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
169 upgradeStDisabled,
170 fsm.Events{
171 {Name: upgradeEvStart, Src: []string{upgradeStDisabled}, Dst: upgradeStStarting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000172 {Name: upgradeEvAdapterDownload, Src: []string{upgradeStStarting}, Dst: upgradeStWaitingAdapterDL},
173 {Name: upgradeEvPrepareSwDownload, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL}, Dst: upgradeStPreparingDL},
mpagenko80622a52021-02-09 16:53:23 +0000174 {Name: upgradeEvRxStartSwDownload, Src: []string{upgradeStPreparingDL}, Dst: upgradeStDLSection},
175 {Name: upgradeEvWaitWindowAck, Src: []string{upgradeStDLSection}, Dst: upgradeStVerifyWindow},
176 {Name: upgradeEvContinueNextWindow, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStDLSection},
177 {Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
mpagenko59498c12021-03-18 14:15:15 +0000178 {Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
179 {Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
mpagenkoc26d4c02021-05-06 14:27:57 +0000180 {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStWaitForActivate},
181 {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStWaitForActivate},
182 Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
mpagenko80622a52021-02-09 16:53:23 +0000183 {Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
184 {Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStWaitForCommit},
mpagenkoc26d4c02021-05-06 14:27:57 +0000185 Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
mpagenko15ff4a52021-03-02 10:09:20 +0000186 {Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000187
188 /*
189 {Name: upgradeEvTimeoutSimple, Src: []string{
190 upgradeStCreatingDot1PMapper, upgradeStCreatingMBPCD, upgradeStSettingTconts, upgradeStSettingDot1PMapper}, Dst: upgradeStStarting},
191 {Name: upgradeEvTimeoutMids, Src: []string{
192 upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
193 */
194 // exceptional treatments
mpagenkoc26d4c02021-05-06 14:27:57 +0000195 {Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
196 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStWaitForActivate,
197 upgradeStRequestingActivate, upgradeStCommitSw, upgradeStCheckCommitted}, //upgradeStWaitForCommit is not reset (later perhaps also not upgradeStWaitActivate)
mpagenko80622a52021-02-09 16:53:23 +0000198 Dst: upgradeStResetting},
mpagenkoc26d4c02021-05-06 14:27:57 +0000199 {Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
200 upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStWaitForActivate,
201 upgradeStRequestingActivate, upgradeStWaitForCommit, upgradeStCommitSw, upgradeStCheckCommitted},
mpagenko80622a52021-02-09 16:53:23 +0000202 Dst: upgradeStResetting},
203 {Name: upgradeEvRestart, Src: []string{upgradeStResetting}, Dst: upgradeStDisabled},
204 },
205 fsm.Callbacks{
206 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
207 "enter_" + upgradeStStarting: func(e *fsm.Event) { instFsm.enterStarting(ctx, e) },
mpagenkoc26d4c02021-05-06 14:27:57 +0000208 "enter_" + upgradeStWaitingAdapterDL: func(e *fsm.Event) { instFsm.enterWaitingAdapterDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000209 "enter_" + upgradeStPreparingDL: func(e *fsm.Event) { instFsm.enterPreparingDL(ctx, e) },
210 "enter_" + upgradeStDLSection: func(e *fsm.Event) { instFsm.enterDownloadSection(ctx, e) },
211 "enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
212 "enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
mpagenko59498c12021-03-18 14:15:15 +0000213 "enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000214 "enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
215 "enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
mpagenko15ff4a52021-03-02 10:09:20 +0000216 "enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
mpagenko80622a52021-02-09 16:53:23 +0000217 "enter_" + upgradeStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
218 "enter_" + upgradeStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
219 },
220 )
221 if instFsm.pAdaptFsm.pFsm == nil {
222 logger.Errorw(ctx, "OnuUpgradeFsm's Base FSM could not be instantiated!!", log.Fields{
223 "device-id": instFsm.deviceID})
224 return nil
225 }
226
227 logger.Debugw(ctx, "OnuUpgradeFsm created", log.Fields{"device-id": instFsm.deviceID})
228 return instFsm
229}
230
231//SetDownloadParams configures the needed parameters for a specific download to the ONU
mpagenkoc26d4c02021-05-06 14:27:57 +0000232// called from 'old' API Activate_image_update()
mpagenko15ff4a52021-03-02 10:09:20 +0000233func (oFsm *OnuUpgradeFsm) SetDownloadParams(ctx context.Context, aInactiveImageID uint16,
234 apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
mpagenko80622a52021-02-09 16:53:23 +0000235 pBaseFsm := oFsm.pAdaptFsm.pFsm
236 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
237 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
238 "device-id": oFsm.deviceID, "image-description": apImageDsc})
mpagenko15ff4a52021-03-02 10:09:20 +0000239 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
mpagenko80622a52021-02-09 16:53:23 +0000240 oFsm.pImageDsc = apImageDsc
241 oFsm.pDownloadManager = apDownloadManager
242
243 go func(aPBaseFsm *fsm.FSM) {
mpagenkoc26d4c02021-05-06 14:27:57 +0000244 // let the upgrade FSM proceed to PreparingDL
mpagenko80622a52021-02-09 16:53:23 +0000245 _ = aPBaseFsm.Event(upgradeEvPrepareSwDownload)
246 }(pBaseFsm)
247 return nil
248 }
249 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
250 "device-id": oFsm.deviceID})
251 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
252}
253
mpagenkoc26d4c02021-05-06 14:27:57 +0000254//SetDownloadParamsAfterDownload configures the needed parameters for a specific download to the ONU according to
255// updated API interface with R2.8: start download to ONU if the image is downloaded to the adapter
256// called from 'new' API Download_onu_image
257func (oFsm *OnuUpgradeFsm) SetDownloadParamsAfterDownload(ctx context.Context, aInactiveImageID uint16,
258 apImageRequest *voltha.DeviceImageDownloadRequest, apDownloadManager *fileDownloadManager,
259 aImageIdentifier string, aDownloadTimeout time.Duration) error {
260 oFsm.mutexUpgradeParams.Lock()
261 var pBaseFsm *fsm.FSM = nil
262 if oFsm.pAdaptFsm != nil {
263 pBaseFsm = oFsm.pAdaptFsm.pFsm
264 }
265 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
266 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
267 "device-id": oFsm.deviceID, "image-description": apImageRequest})
268 oFsm.useAPIVersion43 = true
269 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
270 oFsm.pFileManager = apDownloadManager
271 oFsm.imageIdentifier = aImageIdentifier
272 oFsm.imageVersion = apImageRequest.Image.Version
273 oFsm.activateImage = apImageRequest.ActivateOnSuccess
274 oFsm.commitImage = apImageRequest.CommitOnSuccess
275 oFsm.downloadToOnuTimeout4MB = aDownloadTimeout
276 //TODO: currently straightforward options activate and commit are expected to be set and (unconditionally) done
277 // for separate handling of these options the FSM must accordingly branch from the concerned states - later
278 oFsm.mutexUpgradeParams.Unlock()
279 _ = pBaseFsm.Event(upgradeEvAdapterDownload) //no need to call the FSM event in background here
280 return nil
281 }
282 oFsm.mutexUpgradeParams.Unlock()
283 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
284 "device-id": oFsm.deviceID})
285 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
286}
287
288//SetActivationParamsRunning sets the activate and commit flags for a running download to the ONU according to adapters rpc call
289// called from 'new' API Activate_onu_image
290func (oFsm *OnuUpgradeFsm) SetActivationParamsRunning(ctx context.Context,
291 aImageIdentifier string, aCommit bool) error {
292 oFsm.mutexUpgradeParams.Lock()
293 //set activate/commit independent from state, if FSM is already beyond concerned states, then it does not matter anyway
294 // (as long as the Imageidentifier is correct)
295 logger.Debugw(ctx, "OnuUpgradeFsm activate/commit parameter setting", log.Fields{
296 "device-id": oFsm.deviceID, "image-id": aImageIdentifier, "commit": aCommit})
297 if aImageIdentifier != oFsm.imageIdentifier {
298 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
299 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
300 oFsm.mutexUpgradeParams.Unlock()
301 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
302 oFsm.deviceID))
303 }
304 oFsm.activateImage = true
305 oFsm.commitImage = aCommit
306 oFsm.mutexUpgradeParams.Unlock()
307 var pBaseFsm *fsm.FSM = nil
308 if oFsm.pAdaptFsm != nil {
309 pBaseFsm = oFsm.pAdaptFsm.pFsm
310 }
311 if pBaseFsm != nil {
312 if pBaseFsm.Is(upgradeStWaitForActivate) {
313 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
314 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
315 }
316 return nil
317 }
318 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
319 "device-id": oFsm.deviceID})
320 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
321}
322
323//SetActivationParamsStart starts upgrade processing with immediate activation
324// called from 'new' API Activate_onu_image
325func (oFsm *OnuUpgradeFsm) SetActivationParamsStart(ctx context.Context, aImageVersion string, aInactiveImageID uint16, aCommit bool) error {
326 oFsm.mutexUpgradeParams.Lock()
327 var pBaseFsm *fsm.FSM = nil
328 if oFsm.pAdaptFsm != nil {
329 pBaseFsm = oFsm.pAdaptFsm.pFsm
330 }
331 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
332 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with activation", log.Fields{
333 "device-id": oFsm.deviceID, "image-version": aImageVersion})
334 oFsm.useAPIVersion43 = true
335 oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
336 oFsm.imageVersion = aImageVersion
337 oFsm.activateImage = true
338 oFsm.commitImage = aCommit
339 oFsm.mutexUpgradeParams.Unlock()
340 //directly request the FSM to activate the image
341 _ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
342 return nil
343 }
344 oFsm.mutexUpgradeParams.Unlock()
345 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
346 "device-id": oFsm.deviceID})
347 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
348}
349
350//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
351// called from 'new' API Commit_onu_image
352func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context, aImageIdentifier string) error {
353 oFsm.mutexUpgradeParams.Lock()
354 //set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
355 // (as long as the Imageidentifier is correct)
356 logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
357 "device-id": oFsm.deviceID, "image-id": aImageIdentifier})
358 if aImageIdentifier != oFsm.imageIdentifier {
359 logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
360 "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
361 oFsm.mutexUpgradeParams.Unlock()
362 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
363 oFsm.deviceID))
364 }
365 oFsm.commitImage = true
366 oFsm.mutexUpgradeParams.Unlock()
367 var pBaseFsm *fsm.FSM = nil
368 if oFsm.pAdaptFsm != nil {
369 pBaseFsm = oFsm.pAdaptFsm.pFsm
370 }
371 if pBaseFsm != nil {
372 if pBaseFsm.Is(upgradeStWaitForCommit) {
373 logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for commit", log.Fields{"device-id": oFsm.deviceID})
374 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
375 }
376 return nil
377 }
378 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
379 "device-id": oFsm.deviceID})
380 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
381}
382
383//SetCommitmentParamsStart starts upgrade processing with immediate commitment
384// called from 'new' API Commit_onu_image
385func (oFsm *OnuUpgradeFsm) SetCommitmentParamsStart(ctx context.Context, aImageVersion string, aActiveImageID uint16) error {
386 oFsm.mutexUpgradeParams.Lock()
387 var pBaseFsm *fsm.FSM = nil
388 if oFsm.pAdaptFsm != nil {
389 pBaseFsm = oFsm.pAdaptFsm.pFsm
390 }
391 if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
392 logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting to start with commitment", log.Fields{
393 "device-id": oFsm.deviceID, "image-version": aImageVersion})
394 oFsm.useAPIVersion43 = true
395 oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
396 oFsm.imageVersion = aImageVersion
397 oFsm.commitImage = true
398 oFsm.mutexUpgradeParams.Unlock()
399 //directly request the FSM to activate the image
400 _ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
401 return nil
402 }
403 oFsm.mutexUpgradeParams.Unlock()
404 logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer or state", log.Fields{
405 "device-id": oFsm.deviceID})
406 return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
407}
408
409//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
410func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context) {
411 //mutex protection is required for possible concurrent access to FSM members
412 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
413 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
414 oFsm.mutexIsAwaitingAdapterDlResponse.RLock()
415 if oFsm.isWaitingForAdapterDlResponse {
416 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
417 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
418 oFsm.chAdapterDlReady <- false
419 } else {
420 oFsm.mutexIsAwaitingAdapterDlResponse.RUnlock()
421 }
422 //chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
423
424 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
425 // specific here: If the FSM is in upgradeStWaitForCommit, it is left there for possibly later commit
426 // this possibly also refers later to (not yet existing) upgradeStWaitForActivate (with ctl API changes)
427 pAdaptFsm := oFsm.pAdaptFsm
428 if pAdaptFsm != nil {
429 // calling FSM events in background to avoid blocking of the caller
430 go func(aPAFsm *AdapterFsm) {
431 if aPAFsm.pFsm != nil {
432 if aPAFsm.pFsm.Is(upgradeStWaitEndDL) {
433 oFsm.chReceiveExpectedResponse <- false //which aborts the FSM (activate was not yet sent)
434 }
435 _ = aPAFsm.pFsm.Event(upgradeEvReset) //anyway and for all other states
436 } //else the FSM seems already to be in some released state
437 }(pAdaptFsm)
438 }
439}
440
mpagenko80622a52021-02-09 16:53:23 +0000441func (oFsm *OnuUpgradeFsm) enterStarting(ctx context.Context, e *fsm.Event) {
442 logger.Debugw(ctx, "OnuUpgradeFsm start", log.Fields{"in state": e.FSM.Current(),
443 "device-id": oFsm.deviceID})
444
445 // start go routine for processing of LockState messages
446 go oFsm.processOmciUpgradeMessages(ctx)
447}
448
mpagenkoc26d4c02021-05-06 14:27:57 +0000449//enterWaitingAdapterDL state can only be reached with useAPIVersion43
450func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
451 logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
452 "device-id": oFsm.deviceID})
453 go oFsm.waitOnDownloadToAdapterReady(ctx, oFsm.chAdapterDlReady)
454 go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
455}
456
mpagenko80622a52021-02-09 16:53:23 +0000457func (oFsm *OnuUpgradeFsm) enterPreparingDL(ctx context.Context, e *fsm.Event) {
458 logger.Debugw(ctx, "OnuUpgradeFsm prepare Download to Onu", log.Fields{"in state": e.FSM.Current(),
459 "device-id": oFsm.deviceID})
460
mpagenkoc26d4c02021-05-06 14:27:57 +0000461 var fileLen int64
462 var err error
463 if oFsm.useAPIVersion43 {
464 //with the new API structure download to adapter is implicit and we have to wait until the image is available
465 fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
466 } else {
467 fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
468 }
mpagenko80622a52021-02-09 16:53:23 +0000469 if err != nil || fileLen > int64(cMaxUint32) {
470 logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
471 "device-id": oFsm.deviceID, "error": err, "length": fileLen})
472 pBaseFsm := oFsm.pAdaptFsm
473 // Can't call FSM Event directly, decoupling it
474 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000475 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000476 }(pBaseFsm)
477 return
478 }
479
mpagenkoc26d4c02021-05-06 14:27:57 +0000480 //copy file content to buffer
mpagenko80622a52021-02-09 16:53:23 +0000481 oFsm.imageBuffer = make([]byte, fileLen)
mpagenkoc26d4c02021-05-06 14:27:57 +0000482 if oFsm.useAPIVersion43 {
483 oFsm.imageBuffer, err = oFsm.pFileManager.GetDownloadImageBuffer(ctx, oFsm.imageIdentifier)
484 } else {
485 oFsm.imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
486 }
mpagenko80622a52021-02-09 16:53:23 +0000487 if err != nil {
488 logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
489 "device-id": oFsm.deviceID, "error": err})
490 pBaseFsm := oFsm.pAdaptFsm
491 // Can't call FSM Event directly, decoupling it
492 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000493 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000494 }(pBaseFsm)
495 return
496 }
497
498 oFsm.noOfSections = uint32(fileLen / cOmciDownloadSectionSize)
499 if fileLen%cOmciDownloadSectionSize > 0 {
mpagenkoc26d4c02021-05-06 14:27:57 +0000500 bufferPadding := make([]byte, cOmciDownloadSectionSize-uint32((fileLen)%cOmciDownloadSectionSize))
mpagenko80622a52021-02-09 16:53:23 +0000501 //expand the imageBuffer to exactly fit multiples of cOmciDownloadSectionSize with padding
mpagenkoc26d4c02021-05-06 14:27:57 +0000502 oFsm.imageBuffer = append(oFsm.imageBuffer[:(fileLen)], bufferPadding...)
mpagenko80622a52021-02-09 16:53:23 +0000503 oFsm.noOfSections++
504 }
505 oFsm.origImageLength = uint32(fileLen)
506 oFsm.imageLength = uint32(len(oFsm.imageBuffer))
mpagenko80622a52021-02-09 16:53:23 +0000507
mpagenkoc26d4c02021-05-06 14:27:57 +0000508 go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
509
mpagenko80622a52021-02-09 16:53:23 +0000510 logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
511 "MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
512 "ImageSize": oFsm.imageLength, "original file size": fileLen})
513 //"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
Girish Gowdra0b235842021-03-09 13:06:46 -0800514 err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000515 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
516 if err != nil {
517 logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
518 "device-id": oFsm.deviceID, "error": err})
519 //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
520 pBaseFsm := oFsm.pAdaptFsm
521 // Can't call FSM Event directly, decoupling it
522 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000523 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000524 }(pBaseFsm)
525 return
526 }
527}
528
529func (oFsm *OnuUpgradeFsm) enterDownloadSection(ctx context.Context, e *fsm.Event) {
530 logger.Debugw(ctx, "OnuUpgradeFsm start downloading sections", log.Fields{
531 "device-id": oFsm.deviceID, "absolute window": oFsm.nextDownloadWindow})
532
533 var windowAckRequest uint8 = 0
534 var bufferStartOffset uint32
535 var bufferEndOffset uint32
536 var downloadSection []byte
537 framePrint := false //default no printing of downloadSection frames
538 if oFsm.nextDownloadSectionsAbsolute == 0 {
539 //debug print of first section frame
540 framePrint = true
541 }
542
543 for {
544 bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
545 bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
546 logger.Debugw(ctx, "DlSection values are", log.Fields{
547 "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute,
548 "DlSectionWindow": oFsm.nextDownloadSectionsWindow,
549 "startOffset": bufferStartOffset, "endOffset": bufferEndOffset})
550 if bufferStartOffset+1 > oFsm.imageLength || bufferEndOffset+1 > oFsm.imageLength { //should never occur in this state
551 logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
552 "device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
553 "bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
554 //logical error -- reset the FSM
555 pBaseFsm := oFsm.pAdaptFsm
556 // Can't call FSM Event directly, decoupling it
557 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000558 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000559 }(pBaseFsm)
560 return
561 }
562 downloadSection = oFsm.imageBuffer[bufferStartOffset : bufferEndOffset+1]
563 if oFsm.nextDownloadSectionsWindow == oFsm.omciDownloadWindowSizeLimit {
564 windowAckRequest = 1
565 logger.Debugw(ctx, "DlSection expect Response for complete window", log.Fields{
566 "device-id": oFsm.deviceID, "in window": oFsm.nextDownloadWindow})
567 }
568 if oFsm.nextDownloadSectionsAbsolute+1 >= oFsm.noOfSections {
569 windowAckRequest = 1
570 framePrint = true //debug print of last frame
mpagenko15ff4a52021-03-02 10:09:20 +0000571 oFsm.omciDownloadWindowSizeLast = oFsm.nextDownloadSectionsWindow
572 logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000573 "device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
574 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800575 err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000576 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
577 if err != nil {
578 logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
mpagenko15ff4a52021-03-02 10:09:20 +0000579 "device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
mpagenko80622a52021-02-09 16:53:23 +0000580 //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
581 pBaseFsm := oFsm.pAdaptFsm
582 // Can't call FSM Event directly, decoupling it
583 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000584 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000585 }(pBaseFsm)
586 return
587 }
mpagenko80622a52021-02-09 16:53:23 +0000588 oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
589 if windowAckRequest == 1 {
590 pBaseFsm := oFsm.pAdaptFsm
591 // Can't call FSM Event directly, decoupling it
592 go func(a_pAFsm *AdapterFsm) {
593 _ = a_pAFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
594 }(pBaseFsm)
595 return
596 }
597 framePrint = false //for the next Section frame (if wanted, can be enabled in logic before sendXXX())
598 oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
mpagenko59498c12021-03-18 14:15:15 +0000599 if oFsm.omciSectionInterleaveDelay > 0 {
mpagenko80622a52021-02-09 16:53:23 +0000600 //ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
mpagenko59498c12021-03-18 14:15:15 +0000601 time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
mpagenko80622a52021-02-09 16:53:23 +0000602 }
603 }
604}
605
606func (oFsm *OnuUpgradeFsm) enterVerifyWindow(ctx context.Context, e *fsm.Event) {
607 logger.Debugw(ctx, "OnuUpgradeFsm verify DL window ack", log.Fields{
608 "for window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
609}
610
611func (oFsm *OnuUpgradeFsm) enterFinalizeDL(ctx context.Context, e *fsm.Event) {
mpagenko80622a52021-02-09 16:53:23 +0000612 logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
mpagenko59498c12021-03-18 14:15:15 +0000613 "device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
mpagenko80622a52021-02-09 16:53:23 +0000614
615 if oFsm.delayEndSwDl {
616 //give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
617 // should not be set in case this state is used for real download abort (not yet implemented)
618 time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
619 }
620
mpagenko59498c12021-03-18 14:15:15 +0000621 pBaseFsm := oFsm.pAdaptFsm
622 if pBaseFsm == nil {
623 logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{
624 "device-id": oFsm.deviceID})
625 //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
626 // Can't call FSM Event directly, decoupling it
627 go func(a_pAFsm *AdapterFsm) {
628 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
629 }(pBaseFsm)
630 return
631 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800632 err := oFsm.pOmciCC.sendEndSoftwareDownload(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko59498c12021-03-18 14:15:15 +0000633 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.origImageLength, oFsm.imageCRC)
mpagenko80622a52021-02-09 16:53:23 +0000634 if err != nil {
635 logger.Errorw(ctx, "EndSwDl abort: can't send section", log.Fields{
636 "device-id": oFsm.deviceID, "error": err})
637 //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
mpagenko80622a52021-02-09 16:53:23 +0000638 // Can't call FSM Event directly, decoupling it
639 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000640 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000641 }(pBaseFsm)
642 return
643 }
mpagenko59498c12021-03-18 14:15:15 +0000644 // go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
645 // Can't call FSM Event directly, decoupling it
646 go func(a_pAFsm *AdapterFsm) {
647 _ = a_pAFsm.pFsm.Event(upgradeEvWaitEndDownload)
648 }(pBaseFsm)
649}
650
651func (oFsm *OnuUpgradeFsm) enterWaitEndDL(ctx context.Context, e *fsm.Event) {
652 logger.Infow(ctx, "OnuUpgradeFsm WaitEndDl", log.Fields{
653 "device-id": oFsm.deviceID, "wait delay": oFsm.waitDelayEndSwDl * time.Second, "wait count": oFsm.waitCountEndSwDl})
654 if oFsm.waitCountEndSwDl == 0 {
655 logger.Errorw(ctx, "WaitEndDl abort: max limit of EndSwDL reached", log.Fields{
656 "device-id": oFsm.deviceID})
657 pBaseFsm := oFsm.pAdaptFsm
658 if pBaseFsm == nil {
659 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
660 "device-id": oFsm.deviceID})
661 return
662 }
663 go func(a_pAFsm *AdapterFsm) {
664 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
665 }(pBaseFsm)
666 return
667 }
668
669 oFsm.waitCountEndSwDl--
670 select {
671 case <-time.After(oFsm.waitDelayEndSwDl * time.Second):
672 pBaseFsm := oFsm.pAdaptFsm
673 if pBaseFsm == nil {
674 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
675 "device-id": oFsm.deviceID})
676 //FSM may be reset already from somewhere else, nothing we can do here anymore
677 return
678 }
679 //retry End SW DL
680 oFsm.delayEndSwDl = false //no more extra delay for the request
681 go func(a_pAFsm *AdapterFsm) {
682 _ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
683 }(pBaseFsm)
684 return
685 case success := <-oFsm.chReceiveExpectedResponse:
686 logger.Debugw(ctx, "WaitEndDl stop wait timer", log.Fields{"device-id": oFsm.deviceID})
687 pBaseFsm := oFsm.pAdaptFsm
688 if pBaseFsm == nil {
689 logger.Errorw(ctx, "WaitEndDl abort: BaseFsm invalid", log.Fields{
690 "device-id": oFsm.deviceID})
691 //FSM may be reset already from somewhere else, nothing we can do here anymore
692 return
693 }
694 if success {
695 //answer received with ready indication
mpagenkoc26d4c02021-05-06 14:27:57 +0000696 if oFsm.activateImage {
697 //immediate activation requested
698 go func(a_pAFsm *AdapterFsm) {
699 _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
700 }(pBaseFsm)
701 } else {
702 //have to wait on explicit activation request
703 go func(a_pAFsm *AdapterFsm) {
704 _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
705 }(pBaseFsm)
706 }
mpagenko59498c12021-03-18 14:15:15 +0000707 return
708 }
709 //timer was aborted
710 go func(a_pAFsm *AdapterFsm) {
711 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
712 }(pBaseFsm)
713 return
714 }
mpagenko80622a52021-02-09 16:53:23 +0000715}
716
717func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
718 logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
719 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
720
Girish Gowdra0b235842021-03-09 13:06:46 -0800721 err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko80622a52021-02-09 16:53:23 +0000722 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
723 if err != nil {
724 logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
725 "device-id": oFsm.deviceID, "error": err})
726 //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
727 pBaseFsm := oFsm.pAdaptFsm
728 // Can't call FSM Event directly, decoupling it
729 go func(a_pAFsm *AdapterFsm) {
mpagenko15ff4a52021-03-02 10:09:20 +0000730 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000731 }(pBaseFsm)
732 return
733 }
734}
735
736func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
mpagenko15ff4a52021-03-02 10:09:20 +0000737 if activeImageID, err := oFsm.pOnuOmciDevice.GetActiveImageMeID(ctx); err == nil {
738 //TODO!!: as long as testing with BBSIM and BBSIM not support upgrade tests following check needs to be deactivated
739 imageFit := true //TODO!!: test workaround as long as BBSIM does not fully support upgrade
740 if imageFit || activeImageID == oFsm.inactiveImageMeID {
741 logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
742 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID}) //more efficient activeImageID with above check
Girish Gowdra0b235842021-03-09 13:06:46 -0800743 err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
mpagenko15ff4a52021-03-02 10:09:20 +0000744 oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID) //more efficient activeImageID with above check
745 if err != nil {
746 logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
747 "device-id": oFsm.deviceID, "error": err})
748 //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
749 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
750 pBaseFsm := oFsm.pAdaptFsm
751 // Can't call FSM Event directly, decoupling it
752 go func(a_pAFsm *AdapterFsm) {
753 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
754 }(pBaseFsm)
755 return
756 }
757 return
758 }
759 logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
760 "device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
761 //TODO!!!: possibly send event information for aborted upgrade (not activated)??
762 pBaseFsm := oFsm.pAdaptFsm
763 // Can't call FSM Event directly, decoupling it
764 go func(a_pAFsm *AdapterFsm) {
765 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
766 }(pBaseFsm)
767 return
768 }
769 logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
770 "device-id": oFsm.deviceID})
771 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
772 pBaseFsm := oFsm.pAdaptFsm
773 // Can't call FSM Event directly, decoupling it
774 go func(a_pAFsm *AdapterFsm) {
775 _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
776 }(pBaseFsm)
777}
778
779func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
780 logger.Infow(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
mpagenko80622a52021-02-09 16:53:23 +0000781 "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
mpagenko15ff4a52021-03-02 10:09:20 +0000782 requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
ozgecanetsiab36ed572021-04-01 10:38:48 +0300783 meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
Girish Gowdra0b235842021-03-09 13:06:46 -0800784 me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
mpagenko15ff4a52021-03-02 10:09:20 +0000785 //accept also nil as (error) return value for writing to LastTx
786 // - this avoids misinterpretation of new received OMCI messages
ozgecanetsiab36ed572021-04-01 10:38:48 +0300787 if err != nil {
788 logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
789 log.Fields{"device-id": oFsm.deviceID, "Error": err})
790 pOnuUpgradeFsm := oFsm.pAdaptFsm
791 if pOnuUpgradeFsm != nil {
792 go func(a_pAFsm *AdapterFsm) {
793 _ = a_pAFsm.pFsm.Event(upgradeEvReset)
794 }(pOnuUpgradeFsm)
795 }
796 return
797 }
mpagenko15ff4a52021-03-02 10:09:20 +0000798 oFsm.pLastTxMeInstance = meInstance
mpagenko80622a52021-02-09 16:53:23 +0000799}
800
801func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
802 logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
803
mpagenkoc26d4c02021-05-06 14:27:57 +0000804 // in case the download-to-ONU timer is still running - cancel it
805 oFsm.mutexIsAwaitingOnuDlResponse.RLock()
806 if oFsm.isWaitingForOnuDlResponse {
807 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
808 //use channel to indicate that the download response waiting shall be aborted for this device (channel)
809 oFsm.chOnuDlReady <- false
810 } else {
811 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
812 }
813
mpagenko80622a52021-02-09 16:53:23 +0000814 pConfigupgradeStateAFsm := oFsm.pAdaptFsm
815 if pConfigupgradeStateAFsm != nil {
816 // abort running message processing
817 fsmAbortMsg := Message{
818 Type: TestMsg,
819 Data: TestMessage{
820 TestMessageVal: AbortMessageProcessing,
821 },
822 }
823 pConfigupgradeStateAFsm.commChan <- fsmAbortMsg
824
825 //try to restart the FSM to 'disabled'
826 // Can't call FSM Event directly, decoupling it
827 go func(a_pAFsm *AdapterFsm) {
828 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
829 _ = a_pAFsm.pFsm.Event(upgradeEvRestart)
830 }
831 }(pConfigupgradeStateAFsm)
832 }
833}
834
835func (oFsm *OnuUpgradeFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
836 logger.Debugw(ctx, "OnuUpgradeFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +0000837 // 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 +0000838 if oFsm.pDeviceHandler != nil {
839 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
840 go oFsm.pDeviceHandler.removeOnuUpgradeFsm(ctx)
841 }
842}
843
844func (oFsm *OnuUpgradeFsm) processOmciUpgradeMessages(ctx context.Context) { //ctx context.Context?
845 logger.Debugw(ctx, "Start OnuUpgradeFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
846loop:
847 for {
848 // case <-ctx.Done():
849 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
850 // break loop
851 message, ok := <-oFsm.pAdaptFsm.commChan
852 if !ok {
853 logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
854 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko15ff4a52021-03-02 10:09:20 +0000855 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000856 break loop
857 }
858 logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
859
860 switch message.Type {
861 case TestMsg:
862 msg, _ := message.Data.(TestMessage)
863 if msg.TestMessageVal == AbortMessageProcessing {
864 logger.Infow(ctx, "OnuUpgradeFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
865 break loop
866 }
867 logger.Warnw(ctx, "OnuUpgradeFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
868 case OMCI:
869 msg, _ := message.Data.(OmciMessage)
870 oFsm.handleOmciOnuUpgradeMessage(ctx, msg)
871 default:
872 logger.Warn(ctx, "OnuUpgradeFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
873 "message.Type": message.Type})
874 }
875 }
876 logger.Infow(ctx, "End OnuUpgradeFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
877}
878
879//nolint: gocyclo
880func (oFsm *OnuUpgradeFsm) handleOmciOnuUpgradeMessage(ctx context.Context, msg OmciMessage) {
881 logger.Debugw(ctx, "Rx OMCI OnuUpgradeFsm Msg", log.Fields{"device-id": oFsm.deviceID,
882 "msgType": msg.OmciMsg.MessageType})
883
884 switch msg.OmciMsg.MessageType {
885 case omci.StartSoftwareDownloadResponseType:
886 {
887 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeStartSoftwareDownloadResponse)
888 if msgLayer == nil {
889 logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
890 log.Fields{"device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000891 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
892 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000893 return
894 }
895 msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
896 if !msgOk {
897 logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
898 log.Fields{"device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000899 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
900 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000901 return
902 }
903 logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
904 "device-id": oFsm.deviceID, "data-fields": msgObj})
905 if msgObj.Result != me.Success {
906 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
907 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
908 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
mpagenko15ff4a52021-03-02 10:09:20 +0000909 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
910 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000911 return
912 }
913 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
914 logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
915 if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
916 // also response WindowSize = 0 is a valid number for used Window size 1
917 logger.Debugw(ctx, "different StartSwDlResponse window size requested by ONU", log.Fields{
918 "acceptedOnuWindowSizeLimit": msgObj.WindowSize, "device-id": oFsm.deviceID})
919 oFsm.omciDownloadWindowSizeLimit = msgObj.WindowSize
920 }
921 oFsm.noOfWindows = oFsm.noOfSections / uint32(oFsm.omciDownloadWindowSizeLimit+1)
922 if oFsm.noOfSections%uint32(oFsm.omciDownloadWindowSizeLimit+1) > 0 {
923 oFsm.noOfWindows++
924 }
925 logger.Debugw(ctx, "OnuUpgradeFsm will use", log.Fields{
926 "windows": oFsm.noOfWindows, "sections": oFsm.noOfSections,
927 "at WindowSizeLimit": oFsm.omciDownloadWindowSizeLimit})
928 oFsm.nextDownloadSectionsAbsolute = 0
929 oFsm.nextDownloadSectionsWindow = 0
930 oFsm.nextDownloadWindow = 0
931
932 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
933 return
934 }
935 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
936 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
937 // TODO!!!: possibly repeat the start request (once)?
mpagenko15ff4a52021-03-02 10:09:20 +0000938 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
939 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000940 return
941 } //StartSoftwareDownloadResponseType
942 case omci.DownloadSectionResponseType:
943 {
mpagenko80622a52021-02-09 16:53:23 +0000944 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDownloadSectionResponse)
945 if msgLayer == nil {
946 logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
947 log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
mpagenko15ff4a52021-03-02 10:09:20 +0000948 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
949 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000950 return
951 }
952 msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
953 if !msgOk {
954 logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
955 log.Fields{"device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000956 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
957 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000958 return
959 }
960 logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
961 "device-id": oFsm.deviceID, "data-fields": msgObj})
962 if msgObj.Result != me.Success {
963 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
964 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenko15ff4a52021-03-02 10:09:20 +0000965 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
966 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +0000967 return
968 }
969 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
970 sectionNumber := msgObj.SectionNumber
mpagenko15ff4a52021-03-02 10:09:20 +0000971 logger.Infow(ctx, "DlSectionResponse received", log.Fields{
972 "window section-number": sectionNumber, "window": oFsm.nextDownloadWindow, "device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +0000973
mpagenko15ff4a52021-03-02 10:09:20 +0000974 oFsm.nextDownloadWindow++
975 if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
976 if sectionNumber != oFsm.omciDownloadWindowSizeLast {
mpagenko02cf1b22021-03-12 17:30:30 +0000977 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
mpagenko15ff4a52021-03-02 10:09:20 +0000978 log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
979 "expected section": oFsm.omciDownloadWindowSizeLast})
980 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
981 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
982 return
983 }
mpagenkoc26d4c02021-05-06 14:27:57 +0000984 oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
985 //CRC computation for all data bytes of the file
986 imageCRC := crc32a.Checksum(oFsm.imageBuffer[:int(oFsm.origImageLength)]) //store internal for multiple usage
987 //revert the retrieved CRC Byte Order (seems not to deliver NetworkByteOrder)
988 var byteSlice []byte = make([]byte, 4)
989 binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
990 oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
mpagenko15ff4a52021-03-02 10:09:20 +0000991 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
992 return
993 }
994 if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
995 logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
mpagenko02cf1b22021-03-12 17:30:30 +0000996 log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
997 "expected section": oFsm.omciDownloadWindowSizeLimit})
mpagenko15ff4a52021-03-02 10:09:20 +0000998 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
999 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1000 return
1001 }
1002 oFsm.nextDownloadSectionsWindow = 0
1003 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
mpagenko80622a52021-02-09 16:53:23 +00001004 return
1005 }
mpagenko80622a52021-02-09 16:53:23 +00001006 logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
1007 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko15ff4a52021-03-02 10:09:20 +00001008 // TODO!!!: possibly repeat the download (section) (once)?
1009 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1010 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001011 return
mpagenko80622a52021-02-09 16:53:23 +00001012 } //DownloadSectionResponseType
1013 case omci.EndSoftwareDownloadResponseType:
1014 {
1015 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeEndSoftwareDownloadResponse)
1016 if msgLayer == nil {
1017 logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
1018 log.Fields{"device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +00001019 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1020 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001021 return
1022 }
1023 msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
1024 if !msgOk {
1025 logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
1026 log.Fields{"device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +00001027 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1028 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001029 return
1030 }
1031 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
1032 "device-id": oFsm.deviceID, "data-fields": msgObj})
1033 if msgObj.Result != me.Success {
mpagenko59498c12021-03-18 14:15:15 +00001034 if msgObj.Result == me.DeviceBusy {
1035 //ONU indicates it is still processing the image - let the FSM just wait and then repeat the request
1036 logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse busy: waiting before sending new request", log.Fields{
1037 "device-id": oFsm.deviceID})
1038 return
1039 }
mpagenko80622a52021-02-09 16:53:23 +00001040 logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
1041 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1042 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
mpagenko15ff4a52021-03-02 10:09:20 +00001043 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1044 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001045 return
1046 }
1047 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1048 logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
mpagenkoc26d4c02021-05-06 14:27:57 +00001049 oFsm.mutexIsAwaitingOnuDlResponse.RLock()
1050 if oFsm.isWaitingForOnuDlResponse {
1051 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1052 //use channel to indicate that the download to ONU was successful
1053 oFsm.chOnuDlReady <- true
1054 } else {
1055 oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
1056 }
mpagenko59498c12021-03-18 14:15:15 +00001057 oFsm.chReceiveExpectedResponse <- true //let the FSM proceed from the waitState
mpagenko80622a52021-02-09 16:53:23 +00001058 return
1059 }
1060 logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
1061 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1062 // TODO!!!: possibly repeat the end request (once)? or verify ONU upgrade state?
mpagenko15ff4a52021-03-02 10:09:20 +00001063 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1064 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001065 return
1066 } //EndSoftwareDownloadResponseType
1067 case omci.ActivateSoftwareResponseType:
1068 {
1069 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeActivateSoftwareResponse)
1070 if msgLayer == nil {
1071 logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
1072 log.Fields{"device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +00001073 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1074 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001075 return
1076 }
1077 msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
1078 if !msgOk {
1079 logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
1080 log.Fields{"device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +00001081 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1082 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001083 return
1084 }
1085 logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
1086 "device-id": oFsm.deviceID, "data-fields": msgObj})
1087 if msgObj.Result != me.Success {
1088 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
1089 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1090 // TODO!!!: error treatment?, perhaps in the end reset the FSM
mpagenko15ff4a52021-03-02 10:09:20 +00001091 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1092 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001093 return
1094 }
1095 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
mpagenko02cf1b22021-03-12 17:30:30 +00001096 logger.Infow(ctx, "Expected ActivateSwResponse received", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +00001097 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
1098 return
1099 }
1100 logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
1101 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
mpagenko15ff4a52021-03-02 10:09:20 +00001102 // TODO!!!: error treatment?
1103 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1104 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
mpagenko80622a52021-02-09 16:53:23 +00001105 return
1106 } //ActivateSoftwareResponseType
mpagenko15ff4a52021-03-02 10:09:20 +00001107 case omci.CommitSoftwareResponseType:
1108 {
1109 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCommitSoftwareResponse)
1110 if msgLayer == nil {
1111 logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
1112 log.Fields{"device-id": oFsm.deviceID})
1113 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1114 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1115 return
1116 }
1117 msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
1118 if !msgOk {
1119 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
1120 log.Fields{"device-id": oFsm.deviceID})
1121 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1122 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1123 return
1124 }
mpagenkobf67a092021-03-17 09:52:28 +00001125 if msgObj.Result != me.Success {
mpagenko15ff4a52021-03-02 10:09:20 +00001126 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
1127 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1128 // TODO!!!: error treatment?, perhaps in the end reset the FSM
1129 return
mpagenkobf67a092021-03-17 09:52:28 +00001130 }
mpagenko15ff4a52021-03-02 10:09:20 +00001131 if msgObj.EntityInstance == oFsm.inactiveImageMeID {
1132 logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
1133 //verifying committed image
1134 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
1135 return
1136 }
1137 logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
1138 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1139 // TODO!!!: error treatment?
1140 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1141 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1142 return
1143 } //CommitSoftwareResponseType
1144 case omci.GetResponseType:
1145 {
1146 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1147 if msgLayer == nil {
1148 logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
1149 log.Fields{"device-id": oFsm.deviceID})
1150 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1151 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1152 return
1153 }
1154 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1155 if !msgOk {
1156 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
1157 log.Fields{"device-id": oFsm.deviceID})
1158 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1159 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1160 return
1161 }
1162 logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
1163 "device-id": oFsm.deviceID, "data-fields": msgObj})
1164 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1165 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1166 if msgObj.Result != me.Success {
1167 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
1168 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1169 // TODO!!!: error treatment?, perhaps in the end reset the FSM
1170 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1171 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1172 return
1173 }
1174 } else {
1175 logger.Warnw(ctx, "OnuUpgradeFsm SwImage unexpected Entity GetResponse data - ignore",
1176 log.Fields{"device-id": oFsm.deviceID})
1177 return
1178 }
1179
1180 meAttributes := msgObj.Attributes
1181 imageIsCommitted := meAttributes["IsCommitted"].(uint8)
1182 imageIsActive := meAttributes["IsActive"].(uint8)
1183 imageVersion := trimStringFromInterface(meAttributes["Version"])
mpagenko02cf1b22021-03-12 17:30:30 +00001184 logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
mpagenko15ff4a52021-03-02 10:09:20 +00001185 log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
1186 "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
mpagenko59498c12021-03-18 14:15:15 +00001187 if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive &&
1188 imageIsCommitted == swIsCommitted {
mpagenkoc26d4c02021-05-06 14:27:57 +00001189 //a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
1190 // indicated in the download image version string (version must be part of the image content itself)
1191 // so checking that might be quite unreliable
1192 //but with new API this was changed, assumption is that omci image version is known at download request and exactly that is used
1193 // in all the API references, so it can and should be checked here now
1194 if oFsm.useAPIVersion43 {
1195 if imageVersion != oFsm.imageVersion {
1196 //new active version indicated on OMCI from ONU is not the expected version
1197 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1198 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
1199 "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
1200 // TODO!!!: error treatment?
1201 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1202 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1203 return
1204 }
1205 logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
1206 log.Fields{"device-id": oFsm.deviceID})
1207 }
mpagenko15ff4a52021-03-02 10:09:20 +00001208 logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
1209 //releasing the upgrade FSM
1210 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvReset)
1211 return
1212 }
1213 logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
1214 log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
1215 // TODO!!!: error treatment?
1216 //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
1217 _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
1218 return
1219 } //GetResponseType
mpagenko80622a52021-02-09 16:53:23 +00001220 default:
1221 {
1222 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
1223 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
1224 return
1225 }
1226 }
1227}
1228
mpagenkoc26d4c02021-05-06 14:27:57 +00001229//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1230func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aWaitChannel chan bool) {
1231 downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
1232 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1233 oFsm.isWaitingForAdapterDlResponse = true
1234 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
mpagenko80622a52021-02-09 16:53:23 +00001235 select {
1236 // maybe be also some outside cancel (but no context modeled for the moment ...)
1237 // case <-ctx.Done():
mpagenkoc26d4c02021-05-06 14:27:57 +00001238 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToAdapterReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1239 case <-time.After(downloadToAdapterTimeout): //10s should be enough for downloading some image to the adapter
1240 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-adapter-download timeout", log.Fields{
1241 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToAdapterTimeout})
1242 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1243 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1244 oFsm.isWaitingForAdapterDlResponse = false
1245 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1246 //the upgrade process has to be aborted
1247 pUpgradeFsm := oFsm.pAdaptFsm
1248 if pUpgradeFsm != nil {
1249 _ = pUpgradeFsm.pFsm.Event(upgradeEvReset)
1250 } else {
1251 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
mpagenko80622a52021-02-09 16:53:23 +00001252 }
mpagenkoc26d4c02021-05-06 14:27:57 +00001253 return
1254
1255 case success := <-aWaitChannel:
1256 if success {
1257 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded received", log.Fields{"device-id": oFsm.deviceID})
1258 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1259 oFsm.isWaitingForAdapterDlResponse = false
1260 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1261 //let the upgrade process proceed
1262 pUpgradeFsm := oFsm.pAdaptFsm
1263 if pUpgradeFsm != nil {
1264 _ = pUpgradeFsm.pFsm.Event(upgradeEvPrepareSwDownload)
1265 } else {
1266 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1267 }
1268 return
1269 }
1270 // waiting was aborted (probably on external request)
1271 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-adapter-download aborted", log.Fields{"device-id": oFsm.deviceID})
1272 oFsm.pFileManager.RemoveReadyRequest(ctx, oFsm.imageIdentifier, aWaitChannel)
1273 oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
1274 oFsm.isWaitingForAdapterDlResponse = false
1275 oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
1276 //the upgrade process has to be aborted
1277 pUpgradeFsm := oFsm.pAdaptFsm
1278 if pUpgradeFsm != nil {
1279 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
1280 } else {
1281 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1282 }
1283 return
mpagenko80622a52021-02-09 16:53:23 +00001284 }
1285}
mpagenkoc26d4c02021-05-06 14:27:57 +00001286
1287//waitOnDownloadToOnuReady state can only be reached with useAPIVersion43 (usage of pFileManager)
1288func (oFsm *OnuUpgradeFsm) waitOnDownloadToOnuReady(ctx context.Context, aWaitChannel chan bool) {
1289 downloadToOnuTimeout := time.Duration(1+(oFsm.imageLength/0x400000)) * oFsm.downloadToOnuTimeout4MB
1290 logger.Debugw(ctx, "OnuUpgradeFsm start download-to-ONU timer", log.Fields{"device-id": oFsm.deviceID,
1291 "duration": downloadToOnuTimeout})
1292 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1293 oFsm.isWaitingForOnuDlResponse = true
1294 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1295 select {
1296 // maybe be also some outside cancel (but no context modeled for the moment ...)
1297 // case <-ctx.Done():
1298 // logger.Infow("OnuUpgradeFsm-waitOnDownloadToOnuReady canceled", log.Fields{"for device-id": oFsm.deviceID})
1299 case <-time.After(downloadToOnuTimeout): //using an image-size depending timout (in minutes)
1300 logger.Warnw(ctx, "OnuUpgradeFsm Waiting-ONU-download timeout", log.Fields{
1301 "for device-id": oFsm.deviceID, "image-id": oFsm.imageIdentifier, "timeout": downloadToOnuTimeout})
1302 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1303 oFsm.isWaitingForOnuDlResponse = false
1304 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1305 //the upgrade process has to be aborted
1306 pUpgradeFsm := oFsm.pAdaptFsm
1307 if pUpgradeFsm != nil {
1308 _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
1309 } else {
1310 logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
1311 }
1312 return
1313
1314 case success := <-aWaitChannel:
1315 if success {
1316 logger.Debugw(ctx, "OnuUpgradeFsm image-downloaded on ONU received", log.Fields{"device-id": oFsm.deviceID})
1317 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1318 oFsm.isWaitingForOnuDlResponse = false
1319 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1320 //all fine, let the FSM proceed like defined from the sender of this event
1321 return
1322 }
1323 // waiting was aborted (assumed here to be caused by
1324 // error detection or cancel at download after upgrade FSM reset/abort)
1325 logger.Debugw(ctx, "OnuUpgradeFsm Waiting-ONU-download aborted", log.Fields{"device-id": oFsm.deviceID})
1326 oFsm.mutexIsAwaitingOnuDlResponse.Lock()
1327 oFsm.isWaitingForOnuDlResponse = false
1328 oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
1329 return
1330 }
1331}