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