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