blob: 47c7b90686986cfa50fb4ab393c04339d0c70dcc [file] [log] [blame]
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +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 mib provides the utilities for managing the onu mib
18package mib
19
20import (
21 "context"
22 "encoding/json"
23 "errors"
24 "fmt"
25 "sync"
26 "time"
27
28 "github.com/looplab/fsm"
mpagenko836a1fd2021-11-01 16:12:42 +000029 "github.com/opencord/omci-lib-go/v2"
30 me "github.com/opencord/omci-lib-go/v2/generated"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000031 "github.com/opencord/voltha-lib-go/v7/pkg/db"
32 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
33 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
Holger Hildebrandt9afc1582021-11-30 16:10:19 +000034 "github.com/opencord/voltha-protos/v5/go/inter_adapter"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000035
36 "github.com/opencord/voltha-lib-go/v7/pkg/log"
37
38 cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
39 devdb "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/devdb"
40 "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/swupg"
41)
42
43// events of MibUpload FSM
44const (
45 UlEvStart = "UlEvStart"
46 UlEvResetMib = "UlEvResetMib"
47 UlEvGetVendorAndSerial = "UlEvGetVendorAndSerial"
48 UlEvGetEquipmentID = "UlEvGetEquipmentId"
49 UlEvGetFirstSwVersion = "UlEvGetFirstSwVersion"
50 UlEvGetSecondSwVersion = "UlEvGetSecondSwVersion"
51 UlEvGetMacAddress = "UlEvGetMacAddress"
52 UlEvGetMibTemplate = "UlEvGetMibTemplate"
53 UlEvUploadMib = "UlEvUploadMib"
Holger Hildebrandt9afc1582021-11-30 16:10:19 +000054 UlEvVerifyAndStoreTPs = "UlEvVerifyAndStoreTPs"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000055 UlEvExamineMds = "UlEvExamineMds"
56 UlEvSuccess = "UlEvSuccess"
57 UlEvMismatch = "UlEvMismatch"
58 UlEvAuditMib = "UlEvAuditMib"
59 UlEvForceResync = "UlEvForceResync"
60 UlEvDiffsFound = "UlEvDiffsFound"
61 UlEvTimeout = "UlEvTimeout"
62 UlEvStop = "UlEvStop"
63)
64
65// states of MibUpload FSM
66const (
67 UlStDisabled = "UlStDisabled"
68 UlStStarting = "UlStStarting"
69 UlStResettingMib = "UlStResettingMib"
70 UlStGettingVendorAndSerial = "UlStGettingVendorAndSerial"
71 UlStGettingEquipmentID = "UlStGettingEquipmentID"
72 UlStGettingFirstSwVersion = "UlStGettingFirstSwVersion"
73 UlStGettingSecondSwVersion = "UlStGettingSecondSwVersion"
74 UlStGettingMacAddress = "UlStGettingMacAddress"
75 UlStGettingMibTemplate = "UlStGettingMibTemplate"
76 UlStUploading = "UlStUploading"
77 UlStUploadDone = "UlStUploadDone"
78 UlStInSync = "UlStInSync"
Holger Hildebrandt9afc1582021-11-30 16:10:19 +000079 UlStVerifyingAndStoringTPs = "UlStVerifyingAndStoringTPs"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000080 UlStExaminingMds = "UlStExaminingMds"
81 UlStResynchronizing = "UlStResynchronizing"
82 UlStExaminingMdsSuccess = "UlStExaminingMdsSuccess"
83 UlStAuditing = "UlStAuditing"
84 UlStReAuditing = "UlStReAuditing"
85 UlStOutOfSync = "UlStOutOfSync"
86)
87
88// CMibUlFsmIdleState - TODO: add comment
89const CMibUlFsmIdleState = UlStInSync
90
91// events of MibDownload FSM
92const (
93 DlEvStart = "DlEvStart"
94 DlEvCreateGal = "DlEvCreateGal"
95 DlEvRxGalResp = "DlEvRxGalResp"
96 DlEvRxOnu2gResp = "DlEvRxOnu2gResp"
97 DlEvRxBridgeResp = "DlEvRxBridgeResp"
98 DlEvTimeoutSimple = "DlEvTimeoutSimple"
99 DlEvTimeoutBridge = "DlEvTimeoutBridge"
100 DlEvReset = "DlEvReset"
101 DlEvRestart = "DlEvRestart"
102)
103
104// states of MibDownload FSM
105const (
106 DlStDisabled = "DlStDisabled"
107 DlStStarting = "DlStStarting"
108 DlStCreatingGal = "DlStCreatingGal"
109 DlStSettingOnu2g = "DlStSettingOnu2g"
110 DlStBridgeInit = "DlStBridgeInit"
111 DlStDownloaded = "DlStDownloaded"
112 DlStResetting = "DlStResetting"
113)
114
115// CMibDlFsmIdleState - TODO: add comment
116const CMibDlFsmIdleState = DlStDisabled
117
118const (
119 // NOTE that this hardcoded to service/voltha as the MIB template is shared across stacks
120 cBasePathMibTemplateKvStore = "service/voltha/omci_mibs/go_templates"
121 cSuffixMibTemplateKvStore = "%s/%s/%s"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000122)
123
124const cEmptyMacAddrString = "000000000000"
125const cEmptySerialNumberString = "0000000000000000"
126
127type uniPersConfig struct {
128 PersUniID uint8 `json:"uni_id"`
129 PersTpPathMap map[uint8]string `json:"PersTpPathMap"` // tp-id to tp-path map
130 PersFlowParams []cmn.UniVlanFlowParams `json:"flow_params"` //as defined in omci_ani_config.go
131}
132
133type onuPersistentData struct {
134 PersOnuID uint32 `json:"onu_id"`
135 PersIntfID uint32 `json:"intf_id"`
136 PersSerialNumber string `json:"serial_number"`
137 PersMacAddress string `json:"mac_address"`
138 PersVendorID string `json:"vendor_id"`
139 PersEquipmentID string `json:"equipment_id"`
140 PersActiveSwVersion string `json:"active_sw_version"`
141 PersAdminState string `json:"admin_state"`
142 PersOperState string `json:"oper_state"`
143 PersUniUnlockDone bool `json:"uni_unlock_done"`
144 PersUniDisableDone bool `json:"uni_disable_done"`
145 PersMibAuditInterval time.Duration `json:"mib_audit_interval"`
146 PersMibLastDbSync uint32 `json:"mib_last_db_sync"`
147 PersMibDataSyncAdpt uint8 `json:"mib_data_sync_adpt"`
148 PersUniConfig []uniPersConfig `json:"uni_config"`
149 PersAlarmAuditInterval time.Duration `json:"alarm_audit_interval"`
150 PersTcontMap map[uint16]uint16 `json:"tcont_map"` //alloc-id to me-instance-id map
151}
152
Holger Hildebrandt9afc1582021-11-30 16:10:19 +0000153//type UniTpidInstances map[uint8]map[uint8]inter_adapter.TechProfileDownloadMessage
154
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000155// OnuDeviceEntry - ONU device info and FSM events.
156type OnuDeviceEntry struct {
157 deviceID string
158 baseDeviceHandler cmn.IdeviceHandler
159 pOpenOnuAc cmn.IopenONUAC
160 pOnuTP cmn.IonuUniTechProf
161 coreClient *vgrpc.Client
162 PDevOmciCC *cmn.OmciCC
163 pOnuDB *devdb.OnuDeviceDB
164 mibTemplateKVStore *db.Backend
165 MutexPersOnuConfig sync.RWMutex
166 SOnuPersistentData onuPersistentData
Holger Hildebrandt9afc1582021-11-30 16:10:19 +0000167 ReconciledTpInstances map[uint8]map[uint8]inter_adapter.TechProfileDownloadMessage
168 MutexReconciledTpInstances sync.RWMutex
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000169 reconcilingFlows bool
170 mutexReconcilingFlowsFlag sync.RWMutex
171 chReconcilingFlowsFinished chan bool //channel to indicate that reconciling of flows has been finished
172 mibTemplatePath string
173 mutexOnuKVStore sync.RWMutex
174 onuKVStore *db.Backend
175 onuKVStorePath string
176 mutexOnuKVStoreProcResult sync.RWMutex
177 onuKVStoreProcResult error //error indication of processing
178 chOnuKvProcessingStep chan uint8
179 mutexOnuSwImageIndications sync.RWMutex
180 onuSwImageIndications cmn.SswImageIndications
181 MutexOnuImageStatus sync.RWMutex
182 POnuImageStatus *swupg.OnuImageStatus
183 //lockDeviceEntries sync.RWMutex
184 mibDbClass func(context.Context) error
185 supportedFsms cmn.OmciDeviceFsms
186 devState cmn.OnuDeviceEvent
187 // Audit and MDS
188 mibAuditInterval time.Duration
189 alarmAuditInterval time.Duration
190 // TODO: periodical mib resync will be implemented with story VOL-3792
191 //mibNextDbResync uint32
192
193 // for mibUpload
194 PMibUploadFsm *cmn.AdapterFsm //could be handled dynamically and more general as pcmn.AdapterFsm - perhaps later
195 mutexLastTxParamStruct sync.RWMutex
196 lastTxParamStruct sLastTxMeParameter
197 // for mibDownload
198 PMibDownloadFsm *cmn.AdapterFsm //could be handled dynamically and more general as pcmn.AdapterFsm - perhaps later
199 //remark: general usage of pAdapterFsm would require generalization of CommChan usage and internal event setting
200 // within the FSM event procedures
201 mutexPLastTxMeInstance sync.RWMutex
202 pLastTxMeInstance *me.ManagedEntity
203 omciMessageReceived chan bool //seperate channel needed by DownloadFsm
204 omciRebootMessageReceivedChannel chan cmn.Message // channel needed by reboot request
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000205}
206
207//NewOnuDeviceEntry returns a new instance of a OnuDeviceEntry
208//mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
209func NewOnuDeviceEntry(ctx context.Context, cc *vgrpc.Client, dh cmn.IdeviceHandler,
210 openonu cmn.IopenONUAC) *OnuDeviceEntry {
211 var onuDeviceEntry OnuDeviceEntry
212 onuDeviceEntry.deviceID = dh.GetDeviceID()
213 logger.Debugw(ctx, "init-onuDeviceEntry", log.Fields{"device-id": onuDeviceEntry.deviceID})
214 onuDeviceEntry.baseDeviceHandler = dh
215 onuDeviceEntry.pOpenOnuAc = openonu
216 onuDeviceEntry.coreClient = cc
217 onuDeviceEntry.devState = cmn.DeviceStatusInit
218 onuDeviceEntry.SOnuPersistentData.PersUniConfig = make([]uniPersConfig, 0)
219 onuDeviceEntry.SOnuPersistentData.PersTcontMap = make(map[uint16]uint16)
Holger Hildebrandt9afc1582021-11-30 16:10:19 +0000220 onuDeviceEntry.ReconciledTpInstances = make(map[uint8]map[uint8]inter_adapter.TechProfileDownloadMessage)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000221 onuDeviceEntry.chReconcilingFlowsFinished = make(chan bool)
222 onuDeviceEntry.reconcilingFlows = false
223 onuDeviceEntry.chOnuKvProcessingStep = make(chan uint8)
224 onuDeviceEntry.omciRebootMessageReceivedChannel = make(chan cmn.Message, 2048)
225 //openomciagent.lockDeviceHandlersMap = sync.RWMutex{}
226 //OMCI related databases are on a per-agent basis. State machines and tasks
227 //are per ONU Vendor
228 //
229 // MIB Synchronization Database - possible overloading from arguments
230 supportedFsms := onuDeviceEntry.pOpenOnuAc.GetSupportedFsms()
231 if supportedFsms != nil {
232 onuDeviceEntry.supportedFsms = *supportedFsms
233 } else {
234 // This branch is currently not used and is for potential future usage of alternative MIB Sync FSMs only!
235 //var mibSyncFsm = NewMibSynchronizer()
236 // use some internal defaults, if not defined from outside
237 onuDeviceEntry.supportedFsms = cmn.OmciDeviceFsms{
238 "mib-synchronizer": {
239 //mibSyncFsm, // Implements the MIB synchronization state machine
240 DatabaseClass: onuDeviceEntry.mibDbVolatileDict, // Implements volatile ME MIB database
241 //true, // Advertise events on OpenOMCI event bus
242 AuditInterval: dh.GetAlarmAuditInterval(), // Time to wait between MIB audits. 0 to disable audits.
243 // map[string]func() error{
244 // "mib-upload": onuDeviceEntry.MibUploadTask,
245 // "mib-template": onuDeviceEntry.MibTemplateTask,
246 // "get-mds": onuDeviceEntry.GetMdsTask,
247 // "mib-audit": onuDeviceEntry.GetMdsTask,
248 // "mib-resync": onuDeviceEntry.MibResyncTask,
249 // "mib-reconcile": onuDeviceEntry.MibReconcileTask,
250 // },
251 },
252 }
253 }
254 onuDeviceEntry.mibDbClass = onuDeviceEntry.supportedFsms["mib-synchronizer"].DatabaseClass
255 logger.Debug(ctx, "access2mibDbClass")
256 go onuDeviceEntry.mibDbClass(ctx)
257 if !dh.IsReconciling() {
258 onuDeviceEntry.mibAuditInterval = onuDeviceEntry.supportedFsms["mib-synchronizer"].AuditInterval
259 onuDeviceEntry.SOnuPersistentData.PersMibAuditInterval = onuDeviceEntry.mibAuditInterval
260 onuDeviceEntry.alarmAuditInterval = dh.GetAlarmAuditInterval()
261 onuDeviceEntry.SOnuPersistentData.PersAlarmAuditInterval = onuDeviceEntry.alarmAuditInterval
262 } else {
263 logger.Debugw(ctx, "reconciling - take audit interval from persistent data", log.Fields{"device-id": onuDeviceEntry.deviceID})
264 // TODO: This is a preparation for VOL-VOL-3811 to preserve config history in case of
265 // vendor- or deviceID-specific configurations via voltctl-commands
266 onuDeviceEntry.mibAuditInterval = onuDeviceEntry.SOnuPersistentData.PersMibAuditInterval
267 onuDeviceEntry.alarmAuditInterval = onuDeviceEntry.SOnuPersistentData.PersAlarmAuditInterval
268 }
269 logger.Debugw(ctx, "MibAuditInterval and AlarmAuditInterval is set to", log.Fields{"mib-audit-interval": onuDeviceEntry.mibAuditInterval,
270 "alarm-audit-interval": onuDeviceEntry.alarmAuditInterval})
271 // TODO: periodical mib resync will be implemented with story VOL-3792
272 //onuDeviceEntry.mibNextDbResync = 0
273
274 // Omci related Mib upload sync state machine
275 mibUploadChan := make(chan cmn.Message, 2048)
276 onuDeviceEntry.PMibUploadFsm = cmn.NewAdapterFsm("MibUpload", onuDeviceEntry.deviceID, mibUploadChan)
277 onuDeviceEntry.PMibUploadFsm.PFsm = fsm.NewFSM(
278 UlStDisabled,
279 fsm.Events{
280
281 {Name: UlEvStart, Src: []string{UlStDisabled}, Dst: UlStStarting},
282
283 {Name: UlEvResetMib, Src: []string{UlStStarting}, Dst: UlStResettingMib},
284 {Name: UlEvGetVendorAndSerial, Src: []string{UlStResettingMib}, Dst: UlStGettingVendorAndSerial},
285 {Name: UlEvGetEquipmentID, Src: []string{UlStGettingVendorAndSerial}, Dst: UlStGettingEquipmentID},
286 {Name: UlEvGetFirstSwVersion, Src: []string{UlStGettingEquipmentID}, Dst: UlStGettingFirstSwVersion},
287 {Name: UlEvGetSecondSwVersion, Src: []string{UlStGettingFirstSwVersion}, Dst: UlStGettingSecondSwVersion},
288 {Name: UlEvGetMacAddress, Src: []string{UlStGettingSecondSwVersion}, Dst: UlStGettingMacAddress},
289 {Name: UlEvGetMibTemplate, Src: []string{UlStGettingMacAddress}, Dst: UlStGettingMibTemplate},
290
291 {Name: UlEvUploadMib, Src: []string{UlStGettingMibTemplate}, Dst: UlStUploading},
Holger Hildebrandt9afc1582021-11-30 16:10:19 +0000292
293 {Name: UlEvVerifyAndStoreTPs, Src: []string{UlStStarting}, Dst: UlStVerifyingAndStoringTPs},
294 {Name: UlEvSuccess, Src: []string{UlStVerifyingAndStoringTPs}, Dst: UlStExaminingMds},
295 {Name: UlEvMismatch, Src: []string{UlStVerifyingAndStoringTPs}, Dst: UlStResettingMib},
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000296
297 {Name: UlEvSuccess, Src: []string{UlStGettingMibTemplate}, Dst: UlStUploadDone},
298 {Name: UlEvSuccess, Src: []string{UlStUploading}, Dst: UlStUploadDone},
299
300 {Name: UlEvSuccess, Src: []string{UlStUploadDone}, Dst: UlStInSync},
301 //{Name: UlEvSuccess, Src: []string{UlStExaminingMds}, Dst: UlStInSync},
302 {Name: UlEvSuccess, Src: []string{UlStExaminingMds}, Dst: UlStExaminingMdsSuccess},
303 // TODO: As long as mib-resynchronizing is not implemented, failed MDS-examination triggers
304 // mib-reset and new provisioning at this point
305 //{Name: UlEvMismatch, Src: []string{UlStExaminingMds}, Dst: UlStResynchronizing},
306 {Name: UlEvMismatch, Src: []string{UlStExaminingMds}, Dst: UlStResettingMib},
307
308 {Name: UlEvSuccess, Src: []string{UlStExaminingMdsSuccess}, Dst: UlStInSync},
309 {Name: UlEvMismatch, Src: []string{UlStExaminingMdsSuccess}, Dst: UlStResettingMib},
310
311 {Name: UlEvAuditMib, Src: []string{UlStInSync}, Dst: UlStAuditing},
312
313 {Name: UlEvSuccess, Src: []string{UlStOutOfSync}, Dst: UlStInSync},
314 {Name: UlEvAuditMib, Src: []string{UlStOutOfSync}, Dst: UlStAuditing},
315
316 {Name: UlEvSuccess, Src: []string{UlStAuditing}, Dst: UlStInSync},
317 {Name: UlEvMismatch, Src: []string{UlStAuditing}, Dst: UlStReAuditing},
318 {Name: UlEvForceResync, Src: []string{UlStAuditing}, Dst: UlStResynchronizing},
319
320 {Name: UlEvSuccess, Src: []string{UlStReAuditing}, Dst: UlStInSync},
321 {Name: UlEvMismatch, Src: []string{UlStReAuditing}, Dst: UlStResettingMib},
322
323 {Name: UlEvSuccess, Src: []string{UlStResynchronizing}, Dst: UlStInSync},
324 {Name: UlEvDiffsFound, Src: []string{UlStResynchronizing}, Dst: UlStOutOfSync},
325
326 {Name: UlEvTimeout, Src: []string{UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipmentID, UlStGettingFirstSwVersion,
Holger Hildebrandt9afc1582021-11-30 16:10:19 +0000327 UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing, UlStVerifyingAndStoringTPs,
328 UlStExaminingMds, UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStStarting},
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000329
330 {Name: UlEvStop, Src: []string{UlStStarting, UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipmentID, UlStGettingFirstSwVersion,
Holger Hildebrandt9afc1582021-11-30 16:10:19 +0000331 UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing, UlStVerifyingAndStoringTPs,
332 UlStExaminingMds, UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStDisabled},
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000333 },
334
335 fsm.Callbacks{
336 "enter_state": func(e *fsm.Event) { onuDeviceEntry.PMibUploadFsm.LogFsmStateChange(ctx, e) },
337 "enter_" + UlStStarting: func(e *fsm.Event) { onuDeviceEntry.enterStartingState(ctx, e) },
338 "enter_" + UlStResettingMib: func(e *fsm.Event) { onuDeviceEntry.enterResettingMibState(ctx, e) },
339 "enter_" + UlStGettingVendorAndSerial: func(e *fsm.Event) { onuDeviceEntry.enterGettingVendorAndSerialState(ctx, e) },
340 "enter_" + UlStGettingEquipmentID: func(e *fsm.Event) { onuDeviceEntry.enterGettingEquipmentIDState(ctx, e) },
341 "enter_" + UlStGettingFirstSwVersion: func(e *fsm.Event) { onuDeviceEntry.enterGettingFirstSwVersionState(ctx, e) },
342 "enter_" + UlStGettingSecondSwVersion: func(e *fsm.Event) { onuDeviceEntry.enterGettingSecondSwVersionState(ctx, e) },
343 "enter_" + UlStGettingMacAddress: func(e *fsm.Event) { onuDeviceEntry.enterGettingMacAddressState(ctx, e) },
344 "enter_" + UlStGettingMibTemplate: func(e *fsm.Event) { onuDeviceEntry.enterGettingMibTemplateState(ctx, e) },
345 "enter_" + UlStUploading: func(e *fsm.Event) { onuDeviceEntry.enterUploadingState(ctx, e) },
346 "enter_" + UlStUploadDone: func(e *fsm.Event) { onuDeviceEntry.enterUploadDoneState(ctx, e) },
347 "enter_" + UlStExaminingMds: func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsState(ctx, e) },
Holger Hildebrandt9afc1582021-11-30 16:10:19 +0000348 "enter_" + UlStVerifyingAndStoringTPs: func(e *fsm.Event) { onuDeviceEntry.enterVerifyingAndStoringTPsState(ctx, e) },
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000349 "enter_" + UlStResynchronizing: func(e *fsm.Event) { onuDeviceEntry.enterResynchronizingState(ctx, e) },
350 "enter_" + UlStExaminingMdsSuccess: func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsSuccessState(ctx, e) },
351 "enter_" + UlStAuditing: func(e *fsm.Event) { onuDeviceEntry.enterAuditingState(ctx, e) },
352 "enter_" + UlStReAuditing: func(e *fsm.Event) { onuDeviceEntry.enterReAuditingState(ctx, e) },
353 "enter_" + UlStOutOfSync: func(e *fsm.Event) { onuDeviceEntry.enterOutOfSyncState(ctx, e) },
354 "enter_" + UlStInSync: func(e *fsm.Event) { onuDeviceEntry.enterInSyncState(ctx, e) },
355 },
356 )
357 // Omci related Mib download state machine
358 mibDownloadChan := make(chan cmn.Message, 2048)
359 onuDeviceEntry.PMibDownloadFsm = cmn.NewAdapterFsm("MibDownload", onuDeviceEntry.deviceID, mibDownloadChan)
360 onuDeviceEntry.PMibDownloadFsm.PFsm = fsm.NewFSM(
361 DlStDisabled,
362 fsm.Events{
363
364 {Name: DlEvStart, Src: []string{DlStDisabled}, Dst: DlStStarting},
365
366 {Name: DlEvCreateGal, Src: []string{DlStStarting}, Dst: DlStCreatingGal},
367 {Name: DlEvRxGalResp, Src: []string{DlStCreatingGal}, Dst: DlStSettingOnu2g},
368 {Name: DlEvRxOnu2gResp, Src: []string{DlStSettingOnu2g}, Dst: DlStBridgeInit},
369 // the bridge state is used for multi ME config for alle UNI related ports
370 // maybe such could be reflected in the state machine as well (port number parametrized)
371 // but that looks not straightforward here - so we keep it simple here for the beginning(?)
372 {Name: DlEvRxBridgeResp, Src: []string{DlStBridgeInit}, Dst: DlStDownloaded},
373
374 {Name: DlEvTimeoutSimple, Src: []string{DlStCreatingGal, DlStSettingOnu2g}, Dst: DlStStarting},
375 {Name: DlEvTimeoutBridge, Src: []string{DlStBridgeInit}, Dst: DlStStarting},
376
377 {Name: DlEvReset, Src: []string{DlStStarting, DlStCreatingGal, DlStSettingOnu2g,
378 DlStBridgeInit, DlStDownloaded}, Dst: DlStResetting},
379 // exceptional treatment for all states except DlStResetting
380 {Name: DlEvRestart, Src: []string{DlStStarting, DlStCreatingGal, DlStSettingOnu2g,
381 DlStBridgeInit, DlStDownloaded, DlStResetting}, Dst: DlStDisabled},
382 },
383
384 fsm.Callbacks{
385 "enter_state": func(e *fsm.Event) { onuDeviceEntry.PMibDownloadFsm.LogFsmStateChange(ctx, e) },
386 "enter_" + DlStStarting: func(e *fsm.Event) { onuDeviceEntry.enterDLStartingState(ctx, e) },
387 "enter_" + DlStCreatingGal: func(e *fsm.Event) { onuDeviceEntry.enterCreatingGalState(ctx, e) },
388 "enter_" + DlStSettingOnu2g: func(e *fsm.Event) { onuDeviceEntry.enterSettingOnu2gState(ctx, e) },
389 "enter_" + DlStBridgeInit: func(e *fsm.Event) { onuDeviceEntry.enterBridgeInitState(ctx, e) },
390 "enter_" + DlStDownloaded: func(e *fsm.Event) { onuDeviceEntry.enterDownloadedState(ctx, e) },
391 "enter_" + DlStResetting: func(e *fsm.Event) { onuDeviceEntry.enterResettingState(ctx, e) },
392 },
393 )
394 if onuDeviceEntry.PMibDownloadFsm == nil || onuDeviceEntry.PMibDownloadFsm.PFsm == nil {
395 logger.Errorw(ctx, "MibDownloadFsm could not be instantiated", log.Fields{"device-id": onuDeviceEntry.deviceID})
396 // TODO some specific error treatment - or waiting for crash ?
397 }
398
399 onuDeviceEntry.mibTemplateKVStore = onuDeviceEntry.baseDeviceHandler.SetBackend(ctx, cBasePathMibTemplateKvStore)
400 if onuDeviceEntry.mibTemplateKVStore == nil {
401 logger.Errorw(ctx, "Can't access mibTemplateKVStore - no backend connection to service",
402 log.Fields{"device-id": onuDeviceEntry.deviceID, "service": cBasePathMibTemplateKvStore})
403 }
404
405 onuDeviceEntry.onuKVStorePath = onuDeviceEntry.deviceID
Holger Hildebrandt60652202021-11-02 11:09:36 +0000406 baseKvStorePath := fmt.Sprintf(cmn.CBasePathOnuKVStore, dh.GetBackendPathPrefix())
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000407 onuDeviceEntry.onuKVStore = onuDeviceEntry.baseDeviceHandler.SetBackend(ctx, baseKvStorePath)
408 if onuDeviceEntry.onuKVStore == nil {
409 logger.Errorw(ctx, "Can't access onuKVStore - no backend connection to service",
410 log.Fields{"device-id": onuDeviceEntry.deviceID, "service": baseKvStorePath})
411 }
412
413 // Alarm Synchronization Database
414
415 //self._alarm_db = None
416 //self._alarm_database_cls = support_classes['alarm-synchronizer']['database']
417 return &onuDeviceEntry
418}
419
420//Start starts (logs) the omci agent
421func (oo *OnuDeviceEntry) Start(ctx context.Context) error {
422 logger.Debugw(ctx, "OnuDeviceEntry-starting", log.Fields{"for device-id": oo.deviceID})
423 if oo.PDevOmciCC == nil {
424 oo.PDevOmciCC = cmn.NewOmciCC(ctx, oo.deviceID, oo.baseDeviceHandler, oo, oo.baseDeviceHandler.GetOnuAlarmManager(), oo.coreClient)
425 if oo.PDevOmciCC == nil {
426 logger.Errorw(ctx, "Could not create devOmciCc - abort", log.Fields{"for device-id": oo.deviceID})
427 return fmt.Errorf("could not create devOmciCc %s", oo.deviceID)
428 }
429 }
430 return nil
431}
432
433//Stop stops/resets the omciCC
434func (oo *OnuDeviceEntry) Stop(ctx context.Context, abResetOmciCC bool) error {
435 logger.Debugw(ctx, "OnuDeviceEntry-stopping", log.Fields{"for device-id": oo.deviceID})
436 if abResetOmciCC && (oo.PDevOmciCC != nil) {
437 _ = oo.PDevOmciCC.Stop(ctx)
438 }
439 //to allow for all event notifications again when re-using the device and omciCC
440 oo.devState = cmn.DeviceStatusInit
441 return nil
442}
443
444// Reboot - TODO: add comment
445func (oo *OnuDeviceEntry) Reboot(ctx context.Context) error {
446 logger.Debugw(ctx, "OnuDeviceEntry-rebooting", log.Fields{"for device-id": oo.deviceID})
447 if oo.PDevOmciCC != nil {
448 if err := oo.PDevOmciCC.SendReboot(ctx, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.omciRebootMessageReceivedChannel); err != nil {
449 logger.Errorw(ctx, "onu didn't reboot", log.Fields{"for device-id": oo.deviceID})
450 return err
451 }
452 }
453 return nil
454}
455
456// WaitForRebootResponse - TODO: add comment
457func (oo *OnuDeviceEntry) WaitForRebootResponse(ctx context.Context, responseChannel chan cmn.Message) error {
458 select {
459 case <-time.After(oo.PDevOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
460 logger.Warnw(ctx, "reboot timeout", log.Fields{"for device-id": oo.deviceID})
461 return fmt.Errorf("rebootTimeout")
462 case data := <-responseChannel:
463 switch data.Data.(cmn.OmciMessage).OmciMsg.MessageType {
464 case omci.RebootResponseType:
465 {
466 msgLayer := (*data.Data.(cmn.OmciMessage).OmciPacket).Layer(omci.LayerTypeRebootResponse)
467 if msgLayer == nil {
468 return fmt.Errorf("omci Msg layer could not be detected for RebootResponseType")
469 }
470 msgObj, msgOk := msgLayer.(*omci.RebootResponse)
471 if !msgOk {
472 return fmt.Errorf("omci Msg layer could not be assigned for RebootResponseType %s", oo.deviceID)
473 }
474 logger.Debugw(ctx, "RebootResponse data", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
475 if msgObj.Result != me.Success {
476 logger.Errorw(ctx, "Omci RebootResponse result error", log.Fields{"device-id": oo.deviceID, "Error": msgObj.Result})
477 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
478 return fmt.Errorf("omci RebootResponse result error indication %s for device %s",
479 msgObj.Result, oo.deviceID)
480 }
481 return nil
482 }
483 }
484 logger.Warnw(ctx, "Reboot response message type error", log.Fields{"for device-id": oo.deviceID})
485 return fmt.Errorf("unexpected OmciResponse type received %s", oo.deviceID)
486 }
487}
488
489//Relay the InSync message via Handler to Rw core - Status update
490func (oo *OnuDeviceEntry) transferSystemEvent(ctx context.Context, devEvent cmn.OnuDeviceEvent) {
491 logger.Debugw(ctx, "relaying system-event", log.Fields{"Event": devEvent})
492 // decouple the handler transfer from further processing here
493 // TODO!!! check if really no synch is required within the system e.g. to ensure following steps ..
494 if devEvent == cmn.MibDatabaseSync {
495 if oo.devState < cmn.MibDatabaseSync { //devState has not been synced yet
496 oo.devState = cmn.MibDatabaseSync
497 go oo.baseDeviceHandler.DeviceProcStatusUpdate(ctx, devEvent)
498 //TODO!!! device control: next step: start MIB capability verification from here ?!!!
499 } else {
500 logger.Debugw(ctx, "mibinsync-event in some already synced state - ignored", log.Fields{"state": oo.devState})
501 }
502 } else if devEvent == cmn.MibDownloadDone {
503 if oo.devState < cmn.MibDownloadDone { //devState has not been synced yet
504 oo.devState = cmn.MibDownloadDone
505 go oo.baseDeviceHandler.DeviceProcStatusUpdate(ctx, devEvent)
506 } else {
507 logger.Debugw(ctx, "mibdownloaddone-event was already seen - ignored", log.Fields{"state": oo.devState})
508 }
509 } else {
510 logger.Warnw(ctx, "device-event not yet handled", log.Fields{"state": devEvent})
511 }
512}
513
514// RestoreDataFromOnuKvStore - TODO: add comment
515func (oo *OnuDeviceEntry) RestoreDataFromOnuKvStore(ctx context.Context) error {
516 if oo.onuKVStore == nil {
517 logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
518 return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", oo.deviceID))
519 }
520 oo.MutexPersOnuConfig.Lock()
521 defer oo.MutexPersOnuConfig.Unlock()
522 oo.SOnuPersistentData =
523 onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
524 oo.mutexOnuKVStore.RLock()
525 Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
526 oo.mutexOnuKVStore.RUnlock()
527 if err == nil {
528 if Value != nil {
529 logger.Debugw(ctx, "ONU-data read",
530 log.Fields{"Key": Value.Key, "device-id": oo.deviceID})
531 tmpBytes, _ := kvstore.ToByte(Value.Value)
532
533 if err = json.Unmarshal(tmpBytes, &oo.SOnuPersistentData); err != nil {
534 logger.Errorw(ctx, "unable to unmarshal ONU-data", log.Fields{"error": err, "device-id": oo.deviceID})
535 return fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-ONU-data-%s", oo.deviceID))
536 }
537 logger.Debugw(ctx, "ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
538 "device-id": oo.deviceID})
539 } else {
540 logger.Debugw(ctx, "no ONU-data found", log.Fields{"path": oo.onuKVStorePath, "device-id": oo.deviceID})
541 return fmt.Errorf("no-ONU-data-found")
542 }
543 } else {
544 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": oo.deviceID})
545 return fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s", oo.deviceID))
546 }
547 return nil
548}
549
550// DeleteDataFromOnuKvStore - TODO: add comment
551func (oo *OnuDeviceEntry) DeleteDataFromOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
552 defer wg.Done()
553
554 if oo.onuKVStore == nil {
555 logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
556 oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: onuKVStore not set"))
557 return
558 }
559 var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
560 go oo.deletePersistentData(ctx, processingStep)
561 if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
562 //timeout or error detected
563 logger.Debugw(ctx, "ONU-data not deleted - abort", log.Fields{"device-id": oo.deviceID})
564 oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: during kv-access"))
565 return
566 }
567}
568
569func (oo *OnuDeviceEntry) deletePersistentData(ctx context.Context, aProcessingStep uint8) {
570
571 logger.Debugw(ctx, "delete and clear internal persistency data", log.Fields{"device-id": oo.deviceID})
572
573 oo.MutexPersOnuConfig.Lock()
574 defer oo.MutexPersOnuConfig.Unlock()
575
576 oo.SOnuPersistentData.PersUniConfig = nil //releasing all UniConfig entries to garbage collector default entry
577 oo.SOnuPersistentData =
578 onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
579 logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
580 oo.mutexOnuKVStore.Lock()
581 err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)
582 oo.mutexOnuKVStore.Unlock()
583 if err != nil {
584 logger.Errorw(ctx, "unable to delete in KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
585 oo.chOnuKvProcessingStep <- 0 //error indication
586 return
587 }
588 oo.chOnuKvProcessingStep <- aProcessingStep //done
589}
590
591// UpdateOnuKvStore - TODO: add comment
592func (oo *OnuDeviceEntry) UpdateOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
593 defer wg.Done()
594
595 if oo.onuKVStore == nil {
596 logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
597 oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: onuKVStore not set"))
598 return
599 }
600 var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
601 go oo.storeDataInOnuKvStore(ctx, processingStep)
602 if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
603 //timeout or error detected
604 logger.Debugw(ctx, "ONU-data not written - abort", log.Fields{"device-id": oo.deviceID})
605 oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: during writing process"))
606 return
607 }
608}
609
610func (oo *OnuDeviceEntry) storeDataInOnuKvStore(ctx context.Context, aProcessingStep uint8) {
611
612 oo.MutexPersOnuConfig.Lock()
613 defer oo.MutexPersOnuConfig.Unlock()
614 //assign values which are not already present when NewOnuDeviceEntry() is called
615 onuIndication := oo.baseDeviceHandler.GetOnuIndication()
616 oo.SOnuPersistentData.PersOnuID = onuIndication.OnuId
617 oo.SOnuPersistentData.PersIntfID = onuIndication.IntfId
618 //TODO: verify usage of these values during restart UC
619 oo.SOnuPersistentData.PersAdminState = onuIndication.AdminState
620 oo.SOnuPersistentData.PersOperState = onuIndication.OperState
621
622 logger.Debugw(ctx, "Update ONU-data in KVStore", log.Fields{"device-id": oo.deviceID, "SOnuPersistentData": oo.SOnuPersistentData})
623
624 Value, err := json.Marshal(oo.SOnuPersistentData)
625 if err != nil {
626 logger.Errorw(ctx, "unable to marshal ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
627 "device-id": oo.deviceID, "err": err})
628 oo.chOnuKvProcessingStep <- 0 //error indication
629 return
630 }
631 oo.pOpenOnuAc.RLockMutexDeviceHandlersMap()
632 if _, exist := oo.pOpenOnuAc.GetDeviceHandler(oo.deviceID); !exist {
633 logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
634 oo.chOnuKvProcessingStep <- aProcessingStep
635 oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
636 return
637 }
638 oo.baseDeviceHandler.RLockMutexDeletionInProgressFlag()
639 if oo.baseDeviceHandler.GetDeletionInProgress() {
640 logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
641 oo.chOnuKvProcessingStep <- aProcessingStep
642 oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
643 oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
644 return
645 }
646 oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
647 oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
648
649 oo.mutexOnuKVStore.Lock()
650 err = oo.onuKVStore.Put(ctx, oo.onuKVStorePath, Value)
651 oo.mutexOnuKVStore.Unlock()
652 if err != nil {
653 logger.Errorw(ctx, "unable to write ONU-data into KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
654 oo.chOnuKvProcessingStep <- 0 //error indication
655 return
656 }
657 oo.chOnuKvProcessingStep <- aProcessingStep //done
658}
659
660// UpdateOnuUniTpPath - TODO: add comment
661func (oo *OnuDeviceEntry) UpdateOnuUniTpPath(ctx context.Context, aUniID uint8, aTpID uint8, aPathString string) bool {
662 /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
663 as also the complete sequence is ensured to 'run to completion' before some new request is accepted
664 no specific concurrency protection to SOnuPersistentData is required here
665 */
666 oo.MutexPersOnuConfig.Lock()
667 defer oo.MutexPersOnuConfig.Unlock()
668
669 for k, v := range oo.SOnuPersistentData.PersUniConfig {
670 if v.PersUniID == aUniID {
671 existingPath, ok := oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID]
672 logger.Debugw(ctx, "PersUniConfig-entry exists", log.Fields{"device-id": oo.deviceID, "uniID": aUniID,
673 "tpID": aTpID, "path": aPathString, "existingPath": existingPath, "ok": ok})
674 if !ok {
675 logger.Debugw(ctx, "tp-does-not-exist", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "tpID": aTpID, "path": aPathString})
676 }
677 if existingPath != aPathString {
678 if aPathString == "" {
679 //existing entry to be deleted
680 logger.Debugw(ctx, "UniTp delete path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
681 oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = ""
682 } else {
683 //existing entry to be modified
684 logger.Debugw(ctx, "UniTp modify path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
685 oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = aPathString
686 }
687 return true
688 }
689 //entry already exists
690 if aPathString == "" {
691 //no active TechProfile
692 logger.Debugw(ctx, "UniTp path has already been removed - no AniSide config to be removed", log.Fields{
693 "device-id": oo.deviceID, "uniID": aUniID})
694 } else {
695 //the given TechProfile already exists and is assumed to be active - update devReason as if the config has been done here
696 //was needed e.g. in voltha POD Tests:Validate authentication on a disabled ONU
697 // (as here the TechProfile has not been removed with the disable-device before the new enable-device)
698 logger.Debugw(ctx, "UniTp path already exists - TechProfile supposed to be active", log.Fields{
699 "device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
700 //no deviceReason update (DeviceProcStatusUpdate) here to ensure 'omci_flows_pushed' state within disable/enable procedure of ATT scenario
701 // (during which the flows are removed/re-assigned but the techProf is left active)
702 //and as the TechProfile is regarded as active we have to verify, if some flow configuration still waits on it
703 // (should not be the case, but should not harm or be more robust ...)
704 // and to be sure, that for some reason the corresponding TpDelete was lost somewhere in history
705 // we also reset a possibly outstanding delete request - repeated TpConfig is regarded as valid for waiting flow config
706 if oo.pOnuTP != nil {
707 oo.pOnuTP.SetProfileToDelete(aUniID, aTpID, false)
708 }
709 go oo.baseDeviceHandler.VerifyVlanConfigRequest(ctx, aUniID, aTpID)
710 }
711 return false //indicate 'no change' - nothing more to do, TechProf inter-adapter message is return with success anyway here
712 }
713 }
714 //no entry exists for uniId
715
716 if aPathString == "" {
717 //delete request in non-existing state , accept as no change
718 logger.Debugw(ctx, "UniTp path already removed", log.Fields{"device-id": oo.deviceID, "uniID": aUniID})
719 return false
720 }
721 //new entry to be created
722 logger.Debugw(ctx, "New UniTp path set", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
723 perSubTpPathMap := make(map[uint8]string)
724 perSubTpPathMap[aTpID] = aPathString
725 oo.SOnuPersistentData.PersUniConfig =
726 append(oo.SOnuPersistentData.PersUniConfig, uniPersConfig{PersUniID: aUniID, PersTpPathMap: perSubTpPathMap, PersFlowParams: make([]cmn.UniVlanFlowParams, 0)})
727 return true
728}
729
730// UpdateOnuUniFlowConfig - TODO: add comment
731func (oo *OnuDeviceEntry) UpdateOnuUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]cmn.UniVlanFlowParams) {
732
733 oo.MutexPersOnuConfig.Lock()
734 defer oo.MutexPersOnuConfig.Unlock()
735
736 for k, v := range oo.SOnuPersistentData.PersUniConfig {
737 if v.PersUniID == aUniID {
738 oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams = make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))
739 copy(oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams, *aUniVlanFlowParams)
740 return
741 }
742 }
743 //flow update was faster than tp-config - create PersUniConfig-entry
744 //TODO!!: following activity to 'add' some new uni entry might not be quite correct if this function is called to clear the data
745 // (e.g after flow removal from RemoveUniFlowParams()).
746 // This has the effect of misleading indication that there is still some active UNI entry, even though there might be only some nil flow entry
747 // The effect of this flaw is that at TechProfile removal there is an additional attempt to remove the entry even though no techProfile exists anymore
748 // The code is not changed here because of the current release lane, changes might have unexpected secondary effects, perhaps later with more elaborate tests
749 tmpConfig := uniPersConfig{PersUniID: aUniID, PersTpPathMap: make(map[uint8]string), PersFlowParams: make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))}
750 copy(tmpConfig.PersFlowParams, *aUniVlanFlowParams)
751 oo.SOnuPersistentData.PersUniConfig = append(oo.SOnuPersistentData.PersUniConfig, tmpConfig)
752}
753
754func (oo *OnuDeviceEntry) waitForTimeoutOrCompletion(
755 ctx context.Context, aChOnuProcessingStep <-chan uint8, aProcessingStep uint8) bool {
756 select {
757 case <-ctx.Done():
758 logger.Warnw(ctx, "processing not completed in-time!",
759 log.Fields{"device-id": oo.deviceID, "error": ctx.Err()})
760 return false
761 case rxStep := <-aChOnuProcessingStep:
762 if rxStep == aProcessingStep {
763 return true
764 }
765 //all other values are not accepted - including 0 for error indication
766 logger.Warnw(ctx, "Invalid processing step received: abort!",
767 log.Fields{"device-id": oo.deviceID,
768 "wantedStep": aProcessingStep, "haveStep": rxStep})
769 return false
770 }
771}
772
773// ResetKvProcessingErrorIndication - TODO: add comment
774func (oo *OnuDeviceEntry) ResetKvProcessingErrorIndication() {
775 oo.mutexOnuKVStoreProcResult.Lock()
776 oo.onuKVStoreProcResult = nil
777 oo.mutexOnuKVStoreProcResult.Unlock()
778}
779
780// GetKvProcessingErrorIndication - TODO: add comment
781func (oo *OnuDeviceEntry) GetKvProcessingErrorIndication() error {
782 oo.mutexOnuKVStoreProcResult.RLock()
783 value := oo.onuKVStoreProcResult
784 oo.mutexOnuKVStoreProcResult.RUnlock()
785 return value
786}
787
788func (oo *OnuDeviceEntry) setKvProcessingErrorIndication(value error) {
789 oo.mutexOnuKVStoreProcResult.Lock()
790 oo.onuKVStoreProcResult = value
791 oo.mutexOnuKVStoreProcResult.Unlock()
792}
793
794// IncrementMibDataSync - TODO: add comment
795func (oo *OnuDeviceEntry) IncrementMibDataSync(ctx context.Context) {
796 oo.MutexPersOnuConfig.Lock()
797 defer oo.MutexPersOnuConfig.Unlock()
798 if oo.SOnuPersistentData.PersMibDataSyncAdpt < 255 {
799 oo.SOnuPersistentData.PersMibDataSyncAdpt++
800 } else {
801 // per G.984 and G.988 overflow starts over at 1 given 0 is reserved for reset
802 oo.SOnuPersistentData.PersMibDataSyncAdpt = 1
803 }
804 logger.Debugf(ctx, "mibDataSync updated - mds: %d - device-id: %s", oo.SOnuPersistentData.PersMibDataSyncAdpt, oo.deviceID)
805}
806
807// ModifySwImageInactiveVersion - updates the inactive SW image version stored
808func (oo *OnuDeviceEntry) ModifySwImageInactiveVersion(ctx context.Context, aImageVersion string) {
809 oo.mutexOnuSwImageIndications.Lock()
810 defer oo.mutexOnuSwImageIndications.Unlock()
811 logger.Debugw(ctx, "software-image set inactive version", log.Fields{
812 "device-id": oo.deviceID, "version": aImageVersion})
813 oo.onuSwImageIndications.InActiveEntityEntry.Version = aImageVersion
814 //inactive SW version is not part of persistency data (yet) - no need to update that
815}
816
817// ModifySwImageActiveCommit - updates the active SW commit flag stored
818func (oo *OnuDeviceEntry) ModifySwImageActiveCommit(ctx context.Context, aCommitted uint8) {
819 oo.mutexOnuSwImageIndications.Lock()
820 defer oo.mutexOnuSwImageIndications.Unlock()
821 logger.Debugw(ctx, "software-image set active entity commit flag", log.Fields{
822 "device-id": oo.deviceID, "committed": aCommitted})
823 oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = aCommitted
824 //commit flag is not part of persistency data (yet) - no need to update that
825}
826
827// GetActiveImageVersion - returns the active SW image version stored
828func (oo *OnuDeviceEntry) GetActiveImageVersion(ctx context.Context) string {
829 oo.mutexOnuSwImageIndications.RLock()
830 if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
831 value := oo.onuSwImageIndications.ActiveEntityEntry.Version
832 oo.mutexOnuSwImageIndications.RUnlock()
833 return value
834 }
835 oo.mutexOnuSwImageIndications.RUnlock()
836 logger.Debugw(ctx, "Active Image is not valid", log.Fields{"device-id": oo.deviceID})
837 return ""
838}
839
840// GetInactiveImageVersion - TODO: add comment
841func (oo *OnuDeviceEntry) GetInactiveImageVersion(ctx context.Context) string {
842 oo.mutexOnuSwImageIndications.RLock()
843 if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
844 value := oo.onuSwImageIndications.InActiveEntityEntry.Version
845 oo.mutexOnuSwImageIndications.RUnlock()
846 return value
847 }
848 oo.mutexOnuSwImageIndications.RUnlock()
849 logger.Debugw(ctx, "Inactive Image is not valid", log.Fields{"device-id": oo.deviceID})
850 return ""
851}
852
853func (oo *OnuDeviceEntry) buildMibTemplatePath() string {
854 oo.MutexPersOnuConfig.RLock()
855 defer oo.MutexPersOnuConfig.RUnlock()
856 return fmt.Sprintf(cSuffixMibTemplateKvStore, oo.SOnuPersistentData.PersVendorID, oo.SOnuPersistentData.PersEquipmentID, oo.SOnuPersistentData.PersActiveSwVersion)
857}
858
859// AllocateFreeTcont - TODO: add comment
860func (oo *OnuDeviceEntry) AllocateFreeTcont(ctx context.Context, allocID uint16) (uint16, bool, error) {
861 logger.Debugw(ctx, "allocate-free-tcont", log.Fields{"device-id": oo.deviceID, "allocID": allocID,
862 "allocated-instances": oo.SOnuPersistentData.PersTcontMap})
863
mpagenko2c3f6c52021-11-23 11:22:10 +0000864 oo.MutexPersOnuConfig.Lock()
865 defer oo.MutexPersOnuConfig.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000866 if entityID, ok := oo.SOnuPersistentData.PersTcontMap[allocID]; ok {
867 //tcont already allocated before, return the used instance-id
868 return entityID, true, nil
869 }
870 //First allocation of tcont. Find a free instance
871 if tcontInstKeys := oo.pOnuDB.GetSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
872 logger.Debugw(ctx, "allocate-free-tcont-db-keys", log.Fields{"device-id": oo.deviceID, "keys": tcontInstKeys})
873 for _, instID := range tcontInstKeys {
874 instExist := false
875 //If this instance exist in map, it means it is not empty. It is allocated before
876 for _, v := range oo.SOnuPersistentData.PersTcontMap {
877 if v == instID {
878 instExist = true
879 break
880 }
881 }
882 if !instExist {
883 oo.SOnuPersistentData.PersTcontMap[allocID] = instID
884 return instID, false, nil
885 }
886 }
887 }
888 return 0, false, fmt.Errorf(fmt.Sprintf("no-free-tcont-left-for-device-%s", oo.deviceID))
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000889}
890
891// FreeTcont - TODO: add comment
892func (oo *OnuDeviceEntry) FreeTcont(ctx context.Context, allocID uint16) {
893 logger.Debugw(ctx, "free-tcont", log.Fields{"device-id": oo.deviceID, "alloc": allocID})
mpagenko2c3f6c52021-11-23 11:22:10 +0000894 oo.MutexPersOnuConfig.Lock()
895 defer oo.MutexPersOnuConfig.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000896 delete(oo.SOnuPersistentData.PersTcontMap, allocID)
897}
898
899// GetDevOmciCC - TODO: add comment
900func (oo *OnuDeviceEntry) GetDevOmciCC() *cmn.OmciCC {
901 return oo.PDevOmciCC
902}
903
904// GetOnuDB - TODO: add comment
905func (oo *OnuDeviceEntry) GetOnuDB() *devdb.OnuDeviceDB {
906 return oo.pOnuDB
907}
908
909// GetPersSerialNumber - TODO: add comment
910func (oo *OnuDeviceEntry) GetPersSerialNumber() string {
mpagenko2c3f6c52021-11-23 11:22:10 +0000911 oo.MutexPersOnuConfig.RLock()
912 defer oo.MutexPersOnuConfig.RUnlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000913 value := oo.SOnuPersistentData.PersSerialNumber
914 return value
915}
916
917// GetPersVendorID - TODO: add comment
918func (oo *OnuDeviceEntry) GetPersVendorID() string {
mpagenko2c3f6c52021-11-23 11:22:10 +0000919 oo.MutexPersOnuConfig.RLock()
920 defer oo.MutexPersOnuConfig.RUnlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000921 value := oo.SOnuPersistentData.PersVendorID
922 return value
923}
924
925// GetPersEquipmentID - TODO: add comment
926func (oo *OnuDeviceEntry) GetPersEquipmentID() string {
mpagenko2c3f6c52021-11-23 11:22:10 +0000927 oo.MutexPersOnuConfig.RLock()
928 defer oo.MutexPersOnuConfig.RUnlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000929 value := oo.SOnuPersistentData.PersEquipmentID
930 return value
931}
932
933// GetMibUploadFsmCommChan - TODO: add comment
934func (oo *OnuDeviceEntry) GetMibUploadFsmCommChan() chan cmn.Message {
935 return oo.PMibUploadFsm.CommChan
936}
937
938// GetMibDownloadFsmCommChan - TODO: add comment
939func (oo *OnuDeviceEntry) GetMibDownloadFsmCommChan() chan cmn.Message {
940 return oo.PMibDownloadFsm.CommChan
941}
942
943// GetOmciRebootMsgRevChan - TODO: add comment
944func (oo *OnuDeviceEntry) GetOmciRebootMsgRevChan() chan cmn.Message {
945 return oo.omciRebootMessageReceivedChannel
946}
947
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000948// GetPersActiveSwVersion - TODO: add comment
949func (oo *OnuDeviceEntry) GetPersActiveSwVersion() string {
mpagenko2c3f6c52021-11-23 11:22:10 +0000950 oo.MutexPersOnuConfig.RLock()
951 defer oo.MutexPersOnuConfig.RUnlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000952 return oo.SOnuPersistentData.PersActiveSwVersion
953}
954
955// SetPersActiveSwVersion - TODO: add comment
956func (oo *OnuDeviceEntry) SetPersActiveSwVersion(value string) {
mpagenko2c3f6c52021-11-23 11:22:10 +0000957 oo.MutexPersOnuConfig.Lock()
958 defer oo.MutexPersOnuConfig.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000959 oo.SOnuPersistentData.PersActiveSwVersion = value
960}
961
mpagenko101ac942021-11-16 15:01:29 +0000962// setReconcilingFlows - TODO: add comment
963func (oo *OnuDeviceEntry) setReconcilingFlows(value bool) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000964 oo.mutexReconcilingFlowsFlag.Lock()
965 oo.reconcilingFlows = value
966 oo.mutexReconcilingFlowsFlag.Unlock()
967}
968
mpagenko101ac942021-11-16 15:01:29 +0000969// SendChReconcilingFlowsFinished - TODO: add comment
Holger Hildebrandtf2fcdd42021-12-15 11:42:19 +0000970func (oo *OnuDeviceEntry) SendChReconcilingFlowsFinished(ctx context.Context, value bool) {
mpagenko101ac942021-11-16 15:01:29 +0000971 if oo != nil { //if the object still exists (might have been already deleted in background)
972 //use asynchronous channel sending to avoid stucking on non-waiting receiver
973 select {
974 case oo.chReconcilingFlowsFinished <- value:
Holger Hildebrandtf2fcdd42021-12-15 11:42:19 +0000975 logger.Debugw(ctx, "reconciling - flows finished sent", log.Fields{"device-id": oo.deviceID})
mpagenko101ac942021-11-16 15:01:29 +0000976 default:
Holger Hildebrandtf2fcdd42021-12-15 11:42:19 +0000977 logger.Infow(ctx, "reconciling - flows finished not sent!", log.Fields{"device-id": oo.deviceID})
mpagenko101ac942021-11-16 15:01:29 +0000978 }
979 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000980}
981
mpagenko101ac942021-11-16 15:01:29 +0000982// isReconcilingFlows - TODO: add comment
983func (oo *OnuDeviceEntry) isReconcilingFlows() bool {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000984 oo.mutexReconcilingFlowsFlag.RLock()
985 value := oo.reconcilingFlows
986 oo.mutexReconcilingFlowsFlag.RUnlock()
987 return value
988}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +0000989
990// PrepareForGarbageCollection - remove references to prepare for garbage collection
991func (oo *OnuDeviceEntry) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
992 logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})
993 oo.baseDeviceHandler = nil
994 oo.pOnuTP = nil
995 if oo.PDevOmciCC != nil {
996 oo.PDevOmciCC.PrepareForGarbageCollection(ctx, aDeviceID)
997 }
998 oo.PDevOmciCC = nil
999}