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