blob: bed9b77ea925025c40b5734fd04355abd4311164 [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) {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000498 logger.Debugw(ctx, "relaying system-event", log.Fields{"device-id": oo.deviceID, "Event": devEvent})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000499 // 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 {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000507 logger.Debugw(ctx, "mibinsync-event in some already synced state - ignored",
508 log.Fields{"device-id": oo.deviceID, "state": oo.devState})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000509 }
510 } else if devEvent == cmn.MibDownloadDone {
511 if oo.devState < cmn.MibDownloadDone { //devState has not been synced yet
512 oo.devState = cmn.MibDownloadDone
513 go oo.baseDeviceHandler.DeviceProcStatusUpdate(ctx, devEvent)
514 } else {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000515 logger.Debugw(ctx, "mibdownloaddone-event was already seen - ignored",
516 log.Fields{"device-id": oo.deviceID, "state": oo.devState})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000517 }
518 } else {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000519 logger.Warnw(ctx, "device-event not yet handled",
520 log.Fields{"device-id": oo.deviceID, "state": devEvent})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000521 }
522}
523
524// RestoreDataFromOnuKvStore - TODO: add comment
525func (oo *OnuDeviceEntry) RestoreDataFromOnuKvStore(ctx context.Context) error {
526 if oo.onuKVStore == nil {
527 logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
528 return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", oo.deviceID))
529 }
530 oo.MutexPersOnuConfig.Lock()
531 defer oo.MutexPersOnuConfig.Unlock()
532 oo.SOnuPersistentData =
533 onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
534 oo.mutexOnuKVStore.RLock()
535 Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
536 oo.mutexOnuKVStore.RUnlock()
537 if err == nil {
538 if Value != nil {
539 logger.Debugw(ctx, "ONU-data read",
540 log.Fields{"Key": Value.Key, "device-id": oo.deviceID})
541 tmpBytes, _ := kvstore.ToByte(Value.Value)
542
543 if err = json.Unmarshal(tmpBytes, &oo.SOnuPersistentData); err != nil {
544 logger.Errorw(ctx, "unable to unmarshal ONU-data", log.Fields{"error": err, "device-id": oo.deviceID})
545 return fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-ONU-data-%s", oo.deviceID))
546 }
547 logger.Debugw(ctx, "ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
548 "device-id": oo.deviceID})
549 } else {
550 logger.Debugw(ctx, "no ONU-data found", log.Fields{"path": oo.onuKVStorePath, "device-id": oo.deviceID})
551 return fmt.Errorf("no-ONU-data-found")
552 }
553 } else {
554 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": oo.deviceID})
555 return fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s", oo.deviceID))
556 }
557 return nil
558}
559
560// DeleteDataFromOnuKvStore - TODO: add comment
561func (oo *OnuDeviceEntry) DeleteDataFromOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
562 defer wg.Done()
563
564 if oo.onuKVStore == nil {
565 logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
566 oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: onuKVStore not set"))
567 return
568 }
569 var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
570 go oo.deletePersistentData(ctx, processingStep)
571 if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
572 //timeout or error detected
573 logger.Debugw(ctx, "ONU-data not deleted - abort", log.Fields{"device-id": oo.deviceID})
574 oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: during kv-access"))
575 return
576 }
577}
578
579func (oo *OnuDeviceEntry) deletePersistentData(ctx context.Context, aProcessingStep uint8) {
580
581 logger.Debugw(ctx, "delete and clear internal persistency data", log.Fields{"device-id": oo.deviceID})
582
583 oo.MutexPersOnuConfig.Lock()
584 defer oo.MutexPersOnuConfig.Unlock()
585
586 oo.SOnuPersistentData.PersUniConfig = nil //releasing all UniConfig entries to garbage collector default entry
587 oo.SOnuPersistentData =
588 onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
589 logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
590 oo.mutexOnuKVStore.Lock()
591 err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)
592 oo.mutexOnuKVStore.Unlock()
593 if err != nil {
594 logger.Errorw(ctx, "unable to delete in KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
595 oo.chOnuKvProcessingStep <- 0 //error indication
596 return
597 }
598 oo.chOnuKvProcessingStep <- aProcessingStep //done
599}
600
601// UpdateOnuKvStore - TODO: add comment
602func (oo *OnuDeviceEntry) UpdateOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
603 defer wg.Done()
604
605 if oo.onuKVStore == nil {
606 logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
607 oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: onuKVStore not set"))
608 return
609 }
610 var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
611 go oo.storeDataInOnuKvStore(ctx, processingStep)
612 if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
613 //timeout or error detected
614 logger.Debugw(ctx, "ONU-data not written - abort", log.Fields{"device-id": oo.deviceID})
615 oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: during writing process"))
616 return
617 }
618}
619
620func (oo *OnuDeviceEntry) storeDataInOnuKvStore(ctx context.Context, aProcessingStep uint8) {
621
622 oo.MutexPersOnuConfig.Lock()
623 defer oo.MutexPersOnuConfig.Unlock()
624 //assign values which are not already present when NewOnuDeviceEntry() is called
625 onuIndication := oo.baseDeviceHandler.GetOnuIndication()
626 oo.SOnuPersistentData.PersOnuID = onuIndication.OnuId
627 oo.SOnuPersistentData.PersIntfID = onuIndication.IntfId
628 //TODO: verify usage of these values during restart UC
629 oo.SOnuPersistentData.PersAdminState = onuIndication.AdminState
630 oo.SOnuPersistentData.PersOperState = onuIndication.OperState
631
632 logger.Debugw(ctx, "Update ONU-data in KVStore", log.Fields{"device-id": oo.deviceID, "SOnuPersistentData": oo.SOnuPersistentData})
633
634 Value, err := json.Marshal(oo.SOnuPersistentData)
635 if err != nil {
636 logger.Errorw(ctx, "unable to marshal ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
637 "device-id": oo.deviceID, "err": err})
638 oo.chOnuKvProcessingStep <- 0 //error indication
639 return
640 }
641 oo.pOpenOnuAc.RLockMutexDeviceHandlersMap()
642 if _, exist := oo.pOpenOnuAc.GetDeviceHandler(oo.deviceID); !exist {
643 logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
644 oo.chOnuKvProcessingStep <- aProcessingStep
645 oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
646 return
647 }
648 oo.baseDeviceHandler.RLockMutexDeletionInProgressFlag()
649 if oo.baseDeviceHandler.GetDeletionInProgress() {
650 logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
651 oo.chOnuKvProcessingStep <- aProcessingStep
652 oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
653 oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
654 return
655 }
656 oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
657 oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
658
659 oo.mutexOnuKVStore.Lock()
660 err = oo.onuKVStore.Put(ctx, oo.onuKVStorePath, Value)
661 oo.mutexOnuKVStore.Unlock()
662 if err != nil {
663 logger.Errorw(ctx, "unable to write ONU-data into KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
664 oo.chOnuKvProcessingStep <- 0 //error indication
665 return
666 }
667 oo.chOnuKvProcessingStep <- aProcessingStep //done
668}
669
670// UpdateOnuUniTpPath - TODO: add comment
671func (oo *OnuDeviceEntry) UpdateOnuUniTpPath(ctx context.Context, aUniID uint8, aTpID uint8, aPathString string) bool {
672 /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
673 as also the complete sequence is ensured to 'run to completion' before some new request is accepted
674 no specific concurrency protection to SOnuPersistentData is required here
675 */
676 oo.MutexPersOnuConfig.Lock()
677 defer oo.MutexPersOnuConfig.Unlock()
678
679 for k, v := range oo.SOnuPersistentData.PersUniConfig {
680 if v.PersUniID == aUniID {
681 existingPath, ok := oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID]
682 logger.Debugw(ctx, "PersUniConfig-entry exists", log.Fields{"device-id": oo.deviceID, "uniID": aUniID,
683 "tpID": aTpID, "path": aPathString, "existingPath": existingPath, "ok": ok})
684 if !ok {
685 logger.Debugw(ctx, "tp-does-not-exist", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "tpID": aTpID, "path": aPathString})
686 }
687 if existingPath != aPathString {
688 if aPathString == "" {
689 //existing entry to be deleted
690 logger.Debugw(ctx, "UniTp delete path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
691 oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = ""
692 } else {
693 //existing entry to be modified
694 logger.Debugw(ctx, "UniTp modify path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
695 oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = aPathString
696 }
697 return true
698 }
699 //entry already exists
700 if aPathString == "" {
701 //no active TechProfile
702 logger.Debugw(ctx, "UniTp path has already been removed - no AniSide config to be removed", log.Fields{
703 "device-id": oo.deviceID, "uniID": aUniID})
704 } else {
705 //the given TechProfile already exists and is assumed to be active - update devReason as if the config has been done here
706 //was needed e.g. in voltha POD Tests:Validate authentication on a disabled ONU
707 // (as here the TechProfile has not been removed with the disable-device before the new enable-device)
708 logger.Debugw(ctx, "UniTp path already exists - TechProfile supposed to be active", log.Fields{
709 "device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
710 //no deviceReason update (DeviceProcStatusUpdate) here to ensure 'omci_flows_pushed' state within disable/enable procedure of ATT scenario
711 // (during which the flows are removed/re-assigned but the techProf is left active)
712 //and as the TechProfile is regarded as active we have to verify, if some flow configuration still waits on it
713 // (should not be the case, but should not harm or be more robust ...)
714 // and to be sure, that for some reason the corresponding TpDelete was lost somewhere in history
715 // we also reset a possibly outstanding delete request - repeated TpConfig is regarded as valid for waiting flow config
716 if oo.pOnuTP != nil {
717 oo.pOnuTP.SetProfileToDelete(aUniID, aTpID, false)
718 }
719 go oo.baseDeviceHandler.VerifyVlanConfigRequest(ctx, aUniID, aTpID)
720 }
721 return false //indicate 'no change' - nothing more to do, TechProf inter-adapter message is return with success anyway here
722 }
723 }
724 //no entry exists for uniId
725
726 if aPathString == "" {
727 //delete request in non-existing state , accept as no change
728 logger.Debugw(ctx, "UniTp path already removed", log.Fields{"device-id": oo.deviceID, "uniID": aUniID})
729 return false
730 }
731 //new entry to be created
732 logger.Debugw(ctx, "New UniTp path set", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
733 perSubTpPathMap := make(map[uint8]string)
734 perSubTpPathMap[aTpID] = aPathString
735 oo.SOnuPersistentData.PersUniConfig =
736 append(oo.SOnuPersistentData.PersUniConfig, uniPersConfig{PersUniID: aUniID, PersTpPathMap: perSubTpPathMap, PersFlowParams: make([]cmn.UniVlanFlowParams, 0)})
737 return true
738}
739
740// UpdateOnuUniFlowConfig - TODO: add comment
741func (oo *OnuDeviceEntry) UpdateOnuUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]cmn.UniVlanFlowParams) {
742
743 oo.MutexPersOnuConfig.Lock()
744 defer oo.MutexPersOnuConfig.Unlock()
745
746 for k, v := range oo.SOnuPersistentData.PersUniConfig {
747 if v.PersUniID == aUniID {
748 oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams = make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))
749 copy(oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams, *aUniVlanFlowParams)
750 return
751 }
752 }
753 //flow update was faster than tp-config - create PersUniConfig-entry
754 //TODO!!: following activity to 'add' some new uni entry might not be quite correct if this function is called to clear the data
755 // (e.g after flow removal from RemoveUniFlowParams()).
756 // 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
757 // 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
758 // The code is not changed here because of the current release lane, changes might have unexpected secondary effects, perhaps later with more elaborate tests
759 tmpConfig := uniPersConfig{PersUniID: aUniID, PersTpPathMap: make(map[uint8]string), PersFlowParams: make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))}
760 copy(tmpConfig.PersFlowParams, *aUniVlanFlowParams)
761 oo.SOnuPersistentData.PersUniConfig = append(oo.SOnuPersistentData.PersUniConfig, tmpConfig)
762}
763
764func (oo *OnuDeviceEntry) waitForTimeoutOrCompletion(
765 ctx context.Context, aChOnuProcessingStep <-chan uint8, aProcessingStep uint8) bool {
766 select {
767 case <-ctx.Done():
768 logger.Warnw(ctx, "processing not completed in-time!",
769 log.Fields{"device-id": oo.deviceID, "error": ctx.Err()})
770 return false
771 case rxStep := <-aChOnuProcessingStep:
772 if rxStep == aProcessingStep {
773 return true
774 }
775 //all other values are not accepted - including 0 for error indication
776 logger.Warnw(ctx, "Invalid processing step received: abort!",
777 log.Fields{"device-id": oo.deviceID,
778 "wantedStep": aProcessingStep, "haveStep": rxStep})
779 return false
780 }
781}
782
783// ResetKvProcessingErrorIndication - TODO: add comment
784func (oo *OnuDeviceEntry) ResetKvProcessingErrorIndication() {
785 oo.mutexOnuKVStoreProcResult.Lock()
786 oo.onuKVStoreProcResult = nil
787 oo.mutexOnuKVStoreProcResult.Unlock()
788}
789
790// GetKvProcessingErrorIndication - TODO: add comment
791func (oo *OnuDeviceEntry) GetKvProcessingErrorIndication() error {
792 oo.mutexOnuKVStoreProcResult.RLock()
793 value := oo.onuKVStoreProcResult
794 oo.mutexOnuKVStoreProcResult.RUnlock()
795 return value
796}
797
798func (oo *OnuDeviceEntry) setKvProcessingErrorIndication(value error) {
799 oo.mutexOnuKVStoreProcResult.Lock()
800 oo.onuKVStoreProcResult = value
801 oo.mutexOnuKVStoreProcResult.Unlock()
802}
803
804// IncrementMibDataSync - TODO: add comment
805func (oo *OnuDeviceEntry) IncrementMibDataSync(ctx context.Context) {
806 oo.MutexPersOnuConfig.Lock()
807 defer oo.MutexPersOnuConfig.Unlock()
808 if oo.SOnuPersistentData.PersMibDataSyncAdpt < 255 {
809 oo.SOnuPersistentData.PersMibDataSyncAdpt++
810 } else {
811 // per G.984 and G.988 overflow starts over at 1 given 0 is reserved for reset
812 oo.SOnuPersistentData.PersMibDataSyncAdpt = 1
813 }
814 logger.Debugf(ctx, "mibDataSync updated - mds: %d - device-id: %s", oo.SOnuPersistentData.PersMibDataSyncAdpt, oo.deviceID)
815}
816
817// ModifySwImageInactiveVersion - updates the inactive SW image version stored
818func (oo *OnuDeviceEntry) ModifySwImageInactiveVersion(ctx context.Context, aImageVersion string) {
819 oo.mutexOnuSwImageIndications.Lock()
820 defer oo.mutexOnuSwImageIndications.Unlock()
821 logger.Debugw(ctx, "software-image set inactive version", log.Fields{
822 "device-id": oo.deviceID, "version": aImageVersion})
823 oo.onuSwImageIndications.InActiveEntityEntry.Version = aImageVersion
824 //inactive SW version is not part of persistency data (yet) - no need to update that
825}
826
827// ModifySwImageActiveCommit - updates the active SW commit flag stored
828func (oo *OnuDeviceEntry) ModifySwImageActiveCommit(ctx context.Context, aCommitted uint8) {
829 oo.mutexOnuSwImageIndications.Lock()
830 defer oo.mutexOnuSwImageIndications.Unlock()
831 logger.Debugw(ctx, "software-image set active entity commit flag", log.Fields{
832 "device-id": oo.deviceID, "committed": aCommitted})
833 oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = aCommitted
834 //commit flag is not part of persistency data (yet) - no need to update that
835}
836
837// GetActiveImageVersion - returns the active SW image version stored
838func (oo *OnuDeviceEntry) GetActiveImageVersion(ctx context.Context) string {
839 oo.mutexOnuSwImageIndications.RLock()
840 if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
841 value := oo.onuSwImageIndications.ActiveEntityEntry.Version
842 oo.mutexOnuSwImageIndications.RUnlock()
843 return value
844 }
845 oo.mutexOnuSwImageIndications.RUnlock()
846 logger.Debugw(ctx, "Active Image is not valid", log.Fields{"device-id": oo.deviceID})
847 return ""
848}
849
850// GetInactiveImageVersion - TODO: add comment
851func (oo *OnuDeviceEntry) GetInactiveImageVersion(ctx context.Context) string {
852 oo.mutexOnuSwImageIndications.RLock()
853 if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
854 value := oo.onuSwImageIndications.InActiveEntityEntry.Version
855 oo.mutexOnuSwImageIndications.RUnlock()
856 return value
857 }
858 oo.mutexOnuSwImageIndications.RUnlock()
859 logger.Debugw(ctx, "Inactive Image is not valid", log.Fields{"device-id": oo.deviceID})
860 return ""
861}
862
863func (oo *OnuDeviceEntry) buildMibTemplatePath() string {
864 oo.MutexPersOnuConfig.RLock()
865 defer oo.MutexPersOnuConfig.RUnlock()
866 return fmt.Sprintf(cSuffixMibTemplateKvStore, oo.SOnuPersistentData.PersVendorID, oo.SOnuPersistentData.PersEquipmentID, oo.SOnuPersistentData.PersActiveSwVersion)
867}
868
869// AllocateFreeTcont - TODO: add comment
870func (oo *OnuDeviceEntry) AllocateFreeTcont(ctx context.Context, allocID uint16) (uint16, bool, error) {
871 logger.Debugw(ctx, "allocate-free-tcont", log.Fields{"device-id": oo.deviceID, "allocID": allocID,
872 "allocated-instances": oo.SOnuPersistentData.PersTcontMap})
873
mpagenko2c3f6c52021-11-23 11:22:10 +0000874 oo.MutexPersOnuConfig.Lock()
875 defer oo.MutexPersOnuConfig.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000876 if entityID, ok := oo.SOnuPersistentData.PersTcontMap[allocID]; ok {
877 //tcont already allocated before, return the used instance-id
878 return entityID, true, nil
879 }
880 //First allocation of tcont. Find a free instance
881 if tcontInstKeys := oo.pOnuDB.GetSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
882 logger.Debugw(ctx, "allocate-free-tcont-db-keys", log.Fields{"device-id": oo.deviceID, "keys": tcontInstKeys})
883 for _, instID := range tcontInstKeys {
884 instExist := false
885 //If this instance exist in map, it means it is not empty. It is allocated before
886 for _, v := range oo.SOnuPersistentData.PersTcontMap {
887 if v == instID {
888 instExist = true
889 break
890 }
891 }
892 if !instExist {
893 oo.SOnuPersistentData.PersTcontMap[allocID] = instID
894 return instID, false, nil
895 }
896 }
897 }
898 return 0, false, fmt.Errorf(fmt.Sprintf("no-free-tcont-left-for-device-%s", oo.deviceID))
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000899}
900
901// FreeTcont - TODO: add comment
902func (oo *OnuDeviceEntry) FreeTcont(ctx context.Context, allocID uint16) {
903 logger.Debugw(ctx, "free-tcont", log.Fields{"device-id": oo.deviceID, "alloc": allocID})
mpagenko2c3f6c52021-11-23 11:22:10 +0000904 oo.MutexPersOnuConfig.Lock()
905 defer oo.MutexPersOnuConfig.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000906 delete(oo.SOnuPersistentData.PersTcontMap, allocID)
907}
908
909// GetDevOmciCC - TODO: add comment
910func (oo *OnuDeviceEntry) GetDevOmciCC() *cmn.OmciCC {
911 return oo.PDevOmciCC
912}
913
914// GetOnuDB - TODO: add comment
915func (oo *OnuDeviceEntry) GetOnuDB() *devdb.OnuDeviceDB {
916 return oo.pOnuDB
917}
918
919// GetPersSerialNumber - TODO: add comment
920func (oo *OnuDeviceEntry) GetPersSerialNumber() 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.PersSerialNumber
924 return value
925}
926
927// GetPersVendorID - TODO: add comment
928func (oo *OnuDeviceEntry) GetPersVendorID() 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.PersVendorID
932 return value
933}
934
935// GetPersEquipmentID - TODO: add comment
936func (oo *OnuDeviceEntry) GetPersEquipmentID() string {
mpagenko2c3f6c52021-11-23 11:22:10 +0000937 oo.MutexPersOnuConfig.RLock()
938 defer oo.MutexPersOnuConfig.RUnlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000939 value := oo.SOnuPersistentData.PersEquipmentID
940 return value
941}
942
943// GetMibUploadFsmCommChan - TODO: add comment
944func (oo *OnuDeviceEntry) GetMibUploadFsmCommChan() chan cmn.Message {
945 return oo.PMibUploadFsm.CommChan
946}
947
948// GetMibDownloadFsmCommChan - TODO: add comment
949func (oo *OnuDeviceEntry) GetMibDownloadFsmCommChan() chan cmn.Message {
950 return oo.PMibDownloadFsm.CommChan
951}
952
953// GetOmciRebootMsgRevChan - TODO: add comment
954func (oo *OnuDeviceEntry) GetOmciRebootMsgRevChan() chan cmn.Message {
955 return oo.omciRebootMessageReceivedChannel
956}
957
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000958// GetPersActiveSwVersion - TODO: add comment
959func (oo *OnuDeviceEntry) GetPersActiveSwVersion() string {
mpagenko2c3f6c52021-11-23 11:22:10 +0000960 oo.MutexPersOnuConfig.RLock()
961 defer oo.MutexPersOnuConfig.RUnlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000962 return oo.SOnuPersistentData.PersActiveSwVersion
963}
964
965// SetPersActiveSwVersion - TODO: add comment
966func (oo *OnuDeviceEntry) SetPersActiveSwVersion(value string) {
mpagenko2c3f6c52021-11-23 11:22:10 +0000967 oo.MutexPersOnuConfig.Lock()
968 defer oo.MutexPersOnuConfig.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000969 oo.SOnuPersistentData.PersActiveSwVersion = value
970}
971
mpagenko101ac942021-11-16 15:01:29 +0000972// setReconcilingFlows - TODO: add comment
973func (oo *OnuDeviceEntry) setReconcilingFlows(value bool) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000974 oo.mutexReconcilingFlowsFlag.Lock()
975 oo.reconcilingFlows = value
976 oo.mutexReconcilingFlowsFlag.Unlock()
977}
978
mpagenko101ac942021-11-16 15:01:29 +0000979// SendChReconcilingFlowsFinished - TODO: add comment
Holger Hildebrandtf2fcdd42021-12-15 11:42:19 +0000980func (oo *OnuDeviceEntry) SendChReconcilingFlowsFinished(ctx context.Context, value bool) {
mpagenko101ac942021-11-16 15:01:29 +0000981 if oo != nil { //if the object still exists (might have been already deleted in background)
982 //use asynchronous channel sending to avoid stucking on non-waiting receiver
983 select {
984 case oo.chReconcilingFlowsFinished <- value:
Holger Hildebrandtf2fcdd42021-12-15 11:42:19 +0000985 logger.Debugw(ctx, "reconciling - flows finished sent", log.Fields{"device-id": oo.deviceID})
mpagenko101ac942021-11-16 15:01:29 +0000986 default:
Holger Hildebrandtf2fcdd42021-12-15 11:42:19 +0000987 logger.Infow(ctx, "reconciling - flows finished not sent!", log.Fields{"device-id": oo.deviceID})
mpagenko101ac942021-11-16 15:01:29 +0000988 }
989 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000990}
991
mpagenko101ac942021-11-16 15:01:29 +0000992// isReconcilingFlows - TODO: add comment
993func (oo *OnuDeviceEntry) isReconcilingFlows() bool {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000994 oo.mutexReconcilingFlowsFlag.RLock()
995 value := oo.reconcilingFlows
996 oo.mutexReconcilingFlowsFlag.RUnlock()
997 return value
998}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +0000999
1000// PrepareForGarbageCollection - remove references to prepare for garbage collection
1001func (oo *OnuDeviceEntry) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
1002 logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})
1003 oo.baseDeviceHandler = nil
1004 oo.pOnuTP = nil
1005 if oo.PDevOmciCC != nil {
1006 oo.PDevOmciCC.PrepareForGarbageCollection(ctx, aDeviceID)
1007 }
1008 oo.PDevOmciCC = nil
1009}
Holger Hildebrandtc56febd2022-02-09 13:23:30 +00001010
1011//SendOnuDeviceEvent sends an ONU DeviceEvent via eventProxy
1012func (oo *OnuDeviceEntry) SendOnuDeviceEvent(ctx context.Context, aDeviceEventName string, aDescription string) {
1013
1014 oo.MutexPersOnuConfig.RLock()
1015 context := make(map[string]string)
1016 context["onu-id"] = strconv.FormatUint(uint64(oo.SOnuPersistentData.PersOnuID), 10)
1017 context["intf-id"] = strconv.FormatUint(uint64(oo.SOnuPersistentData.PersIntfID), 10)
1018 context["onu-serial-number"] = oo.SOnuPersistentData.PersSerialNumber
1019 oo.MutexPersOnuConfig.RUnlock()
1020
1021 deviceEvent := &voltha.DeviceEvent{
1022 ResourceId: oo.deviceID,
1023 DeviceEventName: aDeviceEventName,
1024 Description: aDescription,
1025 Context: context,
1026 }
1027 _ = oo.eventProxy.SendDeviceEvent(ctx, deviceEvent, voltha.EventCategory_COMMUNICATION, voltha.EventSubCategory_ONU, time.Now().Unix())
1028}