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