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