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