blob: 023a1faa72b6b7de1d8347c278cac3df4e238ef1 [file] [log] [blame]
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +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 adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
22 "encoding/hex"
23 "errors"
24 "fmt"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000025 "strconv"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000026 "sync"
27 "time"
28
29 "github.com/gogo/protobuf/proto"
30 "github.com/golang/protobuf/ptypes"
31 "github.com/looplab/fsm"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +000032 me "github.com/opencord/omci-lib-go/generated"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000033 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
mpagenkoaf801632020-07-03 10:00:42 +000034 "github.com/opencord/voltha-lib-go/v3/pkg/db"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000035 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000036 vc "github.com/opencord/voltha-protos/v3/go/common"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000037 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 oop "github.com/opencord/voltha-protos/v3/go/openolt"
39 "github.com/opencord/voltha-protos/v3/go/voltha"
40)
41
42/*
43// Constants for number of retries and for timeout
44const (
45 MaxRetry = 10
46 MaxTimeOutInMs = 500
47)
48*/
49
mpagenko1cc3cb42020-07-27 15:24:38 +000050const (
51 // events of Device FSM
52 devEvDeviceInit = "devEvDeviceInit"
53 devEvGrpcConnected = "devEvGrpcConnected"
54 devEvGrpcDisconnected = "devEvGrpcDisconnected"
55 devEvDeviceUpInd = "devEvDeviceUpInd"
56 devEvDeviceDownInd = "devEvDeviceDownInd"
57)
58const (
59 // states of Device FSM
60 devStNull = "devStNull"
61 devStDown = "devStDown"
62 devStInit = "devStInit"
63 devStConnected = "devStConnected"
64 devStUp = "devStUp"
65)
66
Holger Hildebrandt24d51952020-05-04 14:03:42 +000067//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
68const (
69 pon = voltha.EventSubCategory_PON
70 olt = voltha.EventSubCategory_OLT
71 ont = voltha.EventSubCategory_ONT
72 onu = voltha.EventSubCategory_ONU
73 nni = voltha.EventSubCategory_NNI
74 service = voltha.EventCategory_SERVICE
75 security = voltha.EventCategory_SECURITY
76 equipment = voltha.EventCategory_EQUIPMENT
77 processing = voltha.EventCategory_PROCESSING
78 environment = voltha.EventCategory_ENVIRONMENT
79 communication = voltha.EventCategory_COMMUNICATION
80)
81
82const (
83 cEventObjectType = "ONU"
84)
85const (
86 cOnuActivatedEvent = "ONU_ACTIVATED"
87)
88
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000089//DeviceHandler will interact with the ONU ? device.
90type DeviceHandler struct {
91 deviceID string
92 DeviceType string
93 adminState string
94 device *voltha.Device
95 logicalDeviceID string
96 ProxyAddressID string
97 ProxyAddressType string
Holger Hildebrandt24d51952020-05-04 14:03:42 +000098 parentId string
99 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000100
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000101 coreProxy adapterif.CoreProxy
102 AdapterProxy adapterif.AdapterProxy
103 EventProxy adapterif.EventProxy
104
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000105 pOpenOnuAc *OpenONUAC
106 pDeviceStateFsm *fsm.FSM
107 pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +0000108 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000109 pOnuOmciDevice *OnuDeviceEntry
mpagenkoaf801632020-07-03 10:00:42 +0000110 pOnuTP *OnuUniTechProf
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000111 exitChannel chan int
112 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000113 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +0000114 deviceReason string
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000115 pLockStateFsm *LockStateFsm
116 pUnlockStateFsm *LockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000117
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000118 //flowMgr *OpenOltFlowMgr
119 //eventMgr *OpenOltEventMgr
120 //resourceMgr *rsrcMgr.OpenOltResourceMgr
121
122 //discOnus sync.Map
123 //onus sync.Map
124 //portStats *OpenOltStatisticsMgr
125 //metrics *pmmetrics.PmMetrics
126 stopCollector chan bool
127 stopHeartbeatCheck chan bool
128 activePorts sync.Map
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000129 uniEntityMap map[uint32]*OnuUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000130}
131
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000132//NewDeviceHandler creates a new device handler
133func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *DeviceHandler {
134 var dh DeviceHandler
135 dh.coreProxy = cp
136 dh.AdapterProxy = ap
137 dh.EventProxy = ep
138 cloned := (proto.Clone(device)).(*voltha.Device)
139 dh.deviceID = cloned.Id
140 dh.DeviceType = cloned.Type
141 dh.adminState = "up"
142 dh.device = cloned
143 dh.pOpenOnuAc = adapter
144 dh.exitChannel = make(chan int, 1)
145 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000146 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000147 dh.stopCollector = make(chan bool, 2)
148 dh.stopHeartbeatCheck = make(chan bool, 2)
149 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
150 dh.activePorts = sync.Map{}
151 //TODO initialize the support classes.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000152 dh.uniEntityMap = make(map[uint32]*OnuUniPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000153
154 // Device related state machine
155 dh.pDeviceStateFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000156 devStNull,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000157 fsm.Events{
mpagenko1cc3cb42020-07-27 15:24:38 +0000158 {Name: devEvDeviceInit, Src: []string{devStNull, devStDown}, Dst: devStInit},
159 {Name: devEvGrpcConnected, Src: []string{devStInit}, Dst: devStConnected},
160 {Name: devEvGrpcDisconnected, Src: []string{devStConnected, devStDown}, Dst: devStInit},
161 {Name: devEvDeviceUpInd, Src: []string{devStConnected, devStDown}, Dst: devStUp},
162 {Name: devEvDeviceDownInd, Src: []string{devStUp}, Dst: devStDown},
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000163 },
164 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000165 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
166 ("before_" + devEvDeviceInit): func(e *fsm.Event) { dh.doStateInit(e) },
167 ("after_" + devEvDeviceInit): func(e *fsm.Event) { dh.postInit(e) },
168 ("before_" + devEvGrpcConnected): func(e *fsm.Event) { dh.doStateConnected(e) },
169 ("before_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.doStateInit(e) },
170 ("after_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.postInit(e) },
171 ("before_" + devEvDeviceUpInd): func(e *fsm.Event) { dh.doStateUp(e) },
172 ("before_" + devEvDeviceDownInd): func(e *fsm.Event) { dh.doStateDown(e) },
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000173 },
174 )
mpagenkoaf801632020-07-03 10:00:42 +0000175
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000176 return &dh
177}
178
179// start save the device to the data model
180func (dh *DeviceHandler) Start(ctx context.Context) {
181 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "deviceId": dh.deviceID})
182 // Add the initial device to the local model
183 logger.Debug("device-handler-started")
184}
185
186// stop stops the device dh. Not much to do for now
187func (dh *DeviceHandler) stop(ctx context.Context) {
188 logger.Debug("stopping-device-handler")
189 dh.exitChannel <- 1
190}
191
192// ##########################################################################################
193// DeviceHandler methods that implement the adapters interface requests ##### begin #########
194
195//AdoptDevice adopts the OLT device
196func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
197 logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
198
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000199 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
mpagenko1cc3cb42020-07-27 15:24:38 +0000200 if dh.pDeviceStateFsm.Is(devStNull) {
201 if err := dh.pDeviceStateFsm.Event(devEvDeviceInit); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000202 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
203 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000204 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000205 } else {
206 logger.Debug("AdoptDevice: Agent/device init already done")
207 }
208
209 /*
210 // Now, set the initial PM configuration for that device
211 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
212 logger.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
213 }
214
215 go startCollector(dh)
216 go startHeartbeatCheck(dh)
217 */
218}
219
220//ProcessInterAdapterMessage sends the proxied messages to the target device
221// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
222// is meant, and then send the unmarshalled omci message to this onu
223func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
224 msgID := msg.Header.Id
225 msgType := msg.Header.Type
226 fromTopic := msg.Header.FromTopic
227 toTopic := msg.Header.ToTopic
228 toDeviceID := msg.Header.ToDeviceId
229 proxyDeviceID := msg.Header.ProxyDeviceId
230 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
231 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
232
233 switch msgType {
234 case ic.InterAdapterMessageType_OMCI_REQUEST:
235 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000236 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000237 omciMsg := &ic.InterAdapterOmciMessage{}
238 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000239 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
240 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000241 return err
242 }
243
244 //assuming omci message content is hex coded!
245 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000246 logger.Debugw("inter-adapter-recv-omci", log.Fields{
247 "deviceID": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000248 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000249 pDevEntry := dh.GetOnuDeviceEntry(true)
250 if pDevEntry != nil {
251 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
252 } else {
253 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
254 return errors.New("No valid OnuDevice")
255 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000256 }
257 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
258 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000259 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000260 onu_indication := &oop.OnuIndication{}
261 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000262 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
263 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000264 return err
265 }
266
267 onu_operstate := onu_indication.GetOperState()
268 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
269 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
270 "SNR": onu_indication.GetSerialNumber()})
271
mpagenko3af1f032020-06-10 08:53:41 +0000272 //interface related functions might be error checked ....
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000273 if onu_operstate == "up" {
274 dh.create_interface(onu_indication)
275 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
mpagenko3af1f032020-06-10 08:53:41 +0000276 dh.updateInterface(onu_indication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000277 } else {
278 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
279 return errors.New("InvalidOperState")
280 }
281 }
mpagenkoaf801632020-07-03 10:00:42 +0000282 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
283 {
284 if dh.pOnuTP == nil {
285 //should normally not happen ...
286 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
287 log.Fields{"deviceID": dh.deviceID})
288 return errors.New("TechProfile DLMsg request while onuTechProf instance not setup")
289 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000290 if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
291 // I've seen cases for this request, where the device was already stopped
292 logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"deviceId": dh.deviceID})
293 return errors.New("device-unreachable")
294 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000295
mpagenkoaf801632020-07-03 10:00:42 +0000296 msgBody := msg.GetBody()
297 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
298 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
299 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
300 "deviceID": dh.deviceID, "error": err})
301 return err
302 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000303
mpagenkoaf801632020-07-03 10:00:42 +0000304 // we have to lock access to TechProfile processing based on different messageType calls or
305 // even to fast subsequent calls of the same messageType
306 dh.pOnuTP.lockTpProcMutex()
307 // lock hangs as long as below decoupled or other related TechProfile processing is active
308 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify == true {
309 // if there has been some change for some uni TechProfilePath
310 //in order to allow concurrent calls to other dh instances we do not wait for execution here
311 //but doing so we can not indicate problems to the caller (who does what with that then?)
312 //by now we just assume straightforward successful execution
313 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
314 // possible problems to the caller later autonomously
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000315
mpagenko3dbcdd22020-07-22 07:38:45 +0000316 // deadline context to ensure completion of background routines waited for
317 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
318 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
319 dctx, cancel := context.WithDeadline(context.Background(), deadline)
320
mpagenko1cc3cb42020-07-27 15:24:38 +0000321 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000322 var wg sync.WaitGroup
323 wg.Add(2) // for the 2 go routines to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000324 // attention: deadline completion check and wg.Done is to be done in both routines
325 go dh.pOnuTP.configureUniTp(dctx, techProfMsg.UniId, techProfMsg.Path, &wg)
326 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000327 //the wait.. function is responsible for tpProcMutex.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000328 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
mpagenko1cc3cb42020-07-27 15:24:38 +0000329 return err
mpagenkoaf801632020-07-03 10:00:42 +0000330 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000331 // no change, nothing really to do
332 dh.pOnuTP.unlockTpProcMutex()
333 //return success
334 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000335 }
336 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
337 {
338 if dh.pOnuTP == nil {
339 //should normally not happen ...
340 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
341 log.Fields{"deviceID": dh.deviceID})
342 return errors.New("TechProfile DelGem request while onuTechProf instance not setup")
343 }
344
345 msgBody := msg.GetBody()
346 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
347 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
348 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
349 "deviceID": dh.deviceID, "error": err})
350 return err
351 }
352
353 //compare TECH_PROFILE_DOWNLOAD_REQUEST
354 dh.pOnuTP.lockTpProcMutex()
mpagenko3dbcdd22020-07-22 07:38:45 +0000355
356 // deadline context to ensure completion of background routines waited for
357 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
358 dctx, cancel := context.WithDeadline(context.Background(), deadline)
359
mpagenko1cc3cb42020-07-27 15:24:38 +0000360 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000361 var wg sync.WaitGroup
362 wg.Add(1) // for the 1 go routine to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000363 go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000364 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
365 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000366 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
367 return err
mpagenkoaf801632020-07-03 10:00:42 +0000368 }
369 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
370 {
371 if dh.pOnuTP == nil {
372 //should normally not happen ...
373 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
374 log.Fields{"deviceID": dh.deviceID})
375 return errors.New("TechProfile DelTcont request while onuTechProf instance not setup")
376 }
377
378 msgBody := msg.GetBody()
379 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
380 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
381 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
382 "deviceID": dh.deviceID, "error": err})
383 return err
384 }
385
386 //compare TECH_PROFILE_DOWNLOAD_REQUEST
387 dh.pOnuTP.lockTpProcMutex()
388 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify == true {
mpagenko3dbcdd22020-07-22 07:38:45 +0000389 // deadline context to ensure completion of background routines waited for
390 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
391 dctx, cancel := context.WithDeadline(context.Background(), deadline)
392
mpagenko1cc3cb42020-07-27 15:24:38 +0000393 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000394 var wg sync.WaitGroup
mpagenko3dbcdd22020-07-22 07:38:45 +0000395 wg.Add(2) // for the 2 go routines to finish
396 go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000397 cResourceTcont, delTcontMsg.AllocId, &wg)
398 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
mpagenko3dbcdd22020-07-22 07:38:45 +0000399 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000400 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000401 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
402 return err
mpagenkoaf801632020-07-03 10:00:42 +0000403 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000404 dh.pOnuTP.unlockTpProcMutex()
405 //return success
406 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000407 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000408 default:
409 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000410 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
411 "deviceID": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000412 return errors.New("unimplemented")
413 }
414 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000415 return nil
416}
417
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000418//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000419// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
420// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300421func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000422 logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
423
mpagenko3af1f032020-06-10 08:53:41 +0000424 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
425 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
426 if dh.deviceReason != "omci-admin-lock" {
427 // disable UNI ports/ONU
428 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
429 // here the result of the processing is not checked (trusted in background) *****
430 if dh.pLockStateFsm == nil {
431 dh.createUniLockFsm(true, UniAdminStateDone)
432 } else { //LockStateFSM already init
433 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
434 dh.runUniLockFsm(true)
435 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300436
mpagenko3af1f032020-06-10 08:53:41 +0000437 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
438 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
439 }
440 dh.deviceReason = "omci-admin-lock"
441 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
442 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
443 voltha.OperStatus_UNKNOWN); err != nil {
444 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
445 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300446 }
447}
448
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000449//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000450// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
451// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300452func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000453 logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000454
455 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300456 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
457 voltha.OperStatus_ACTIVE); err != nil {
458 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
459 }
460
mpagenko3af1f032020-06-10 08:53:41 +0000461 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000462 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
ozgecanetsiafce57b12020-05-25 14:39:35 +0300463 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
464 }
mpagenko3af1f032020-06-10 08:53:41 +0000465 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000466
467 // enable ONU/UNI ports
468 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
469 // here the result of the processing is not checked (trusted in background) *****
470 if dh.pUnlockStateFsm == nil {
471 dh.createUniLockFsm(false, UniAdminStateDone)
472 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000473 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000474 dh.runUniLockFsm(false)
475 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300476}
477
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000478func (dh *DeviceHandler) ReconcileDevice(device *voltha.Device) error {
479 logger.Debugw("reconcile-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
480 if err := dh.pOnuTP.restoreFromOnuTpPathKvStore(context.TODO()); err != nil {
481 return err
482 }
483 // TODO: further actions - init PON, metrics, reload DB ...
484 return nil
485}
486
487func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
488 logger.Debugw("delete-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
489 if err := dh.pOnuTP.deleteOnuTpPathKvStore(context.TODO()); err != nil {
490 return err
491 }
492 // TODO: further actions - stop metrics and FSMs, remove device ...
493 return nil
494}
495
ozgecanetsiae11479f2020-07-06 09:44:47 +0300496func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
497 logger.Debugw("reboot-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
498 if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
499 logger.Errorw("device-unreachable", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
500 return errors.New("device-unreachable")
501 }
502 dh.pOnuOmciDevice.Reboot(context.TODO())
503 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
504 voltha.OperStatus_DISCOVERED); err != nil {
505 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
506 return err
507 }
508 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting-onu"); err != nil {
509 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
510 return err
511 }
512 dh.deviceReason = "rebooting-onu"
513 return nil
514}
515
516//GetOfpPortInfo returns the Voltha PortCapabilty with the logical port
517//func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
518// portNo int64) (*ic.PortCapability, error) {
519// logger.Debugw("GetOfpPortInfo start", log.Fields{"deviceID": device.Id, "portNo": portNo})
520
521//function body as per OLTAdapter handler code
522// adapted with values from py dapter code
523// if pUniPort, exist := dh.uniEntityMap[uint32(portNo)]; exist {
524// var macOctets [6]uint8
525// macOctets[5] = 0x08
526// macOctets[4] = uint8(dh.ponPortNumber >> 8)
527// macOctets[3] = uint8(dh.ponPortNumber)
528// macOctets[2] = uint8(portNo >> 16)
529// macOctets[1] = uint8(portNo >> 8)
530// macOctets[0] = uint8(portNo)
531// hwAddr := genMacFromOctets(macOctets)
532// capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
533// name := device.SerialNumber + "-" + strconv.FormatUint(uint64(pUniPort.macBpNo), 10)
534// ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
535// if pUniPort.operState == vc.OperStatus_ACTIVE {
536// ofUniPortState = of.OfpPortState_OFPPS_LIVE
537// }
538// logger.Debugw("setting LogicalPort", log.Fields{"with-name": name,
539// "withUniPort": pUniPort.name, "withMacBase": hwAddr, "OperState": ofUniPortState})
540
541// return &ic.PortCapability{
542// Port: &voltha.LogicalPort{
543// OfpPort: &of.OfpPort{
544// Name: name,
545// //HwAddr: macAddressToUint32Array(dh.device.MacAddress),
546// HwAddr: macAddressToUint32Array(hwAddr),
547// Config: 0,
548// State: uint32(ofUniPortState),
549// Curr: capacity,
550// Advertised: capacity,
551// Peer: capacity,
552// CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
553// MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
554// },
555// DeviceId: device.Id,
556// DevicePortNo: uint32(portNo),
557// },
558// }, nil
559// }
560// logger.Warnw("No UniPort found - abort", log.Fields{"for PortNo": uint32(portNo)})
561// return nil, errors.New("UniPort not found")
562//}
563
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000564// DeviceHandler methods that implement the adapters interface requests## end #########
565// #####################################################################################
566
567// ################ to be updated acc. needs of ONU Device ########################
568// DeviceHandler StateMachine related state transition methods ##### begin #########
569
570func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
571 logger.Debugw("Device FSM: ", log.Fields{"event name": string(e.Event), "src state": string(e.Src), "dst state": string(e.Dst), "device-id": dh.deviceID})
572}
573
574// doStateInit provides the device update to the core
575func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
576
577 logger.Debug("doStateInit-started")
578 var err error
579
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000580 // populate what we know. rest comes later after mib sync
581 dh.device.Root = false
582 dh.device.Vendor = "OpenONU"
583 dh.device.Model = "go"
584 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000585 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000586
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000587 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000588 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
589
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000590 dh.parentId = dh.device.ParentId
591 dh.ponPortNumber = dh.device.ParentPortNo
592
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000593 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
594 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
595 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
596 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
597 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000598 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000599
600 /*
601 self._pon = PonPort.create(self, self._pon_port_number)
602 self._pon.add_peer(self.parent_id, self._pon_port_number)
603 self.logger.debug('adding-pon-port-to-agent',
604 type=self._pon.get_port().type,
605 admin_state=self._pon.get_port().admin_state,
606 oper_status=self._pon.get_port().oper_status,
607 )
608 */
609 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000610 var ponPortNo uint32 = 1
611 if dh.ponPortNumber != 0 {
612 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000613 }
614
615 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000616 PortNo: ponPortNo,
617 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000618 Type: voltha.Port_PON_ONU,
619 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000620 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
621 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000622 }
623 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
624 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
625 e.Cancel(err)
626 return
627 }
628 logger.Debug("doStateInit-done")
629}
630
631// postInit setups the DeviceEntry for the conerned device
632func (dh *DeviceHandler) postInit(e *fsm.Event) {
633
634 logger.Debug("postInit-started")
635 var err error
636 /*
637 dh.Client = oop.NewOpenoltClient(dh.clientCon)
638 dh.pTransitionMap.Handle(ctx, GrpcConnected)
639 return nil
640 */
mpagenko3af1f032020-06-10 08:53:41 +0000641 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
642 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000643 e.Cancel(err)
644 return
645 }
646
647 /*
648 ############################################################################
649 # Setup Alarm handler
650 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
651 device.serial_number)
652 ############################################################################
653 # Setup PM configuration for this device
654 # Pass in ONU specific options
655 kwargs = {
656 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
657 'heartbeat': self.heartbeat,
658 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
659 }
660 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
661 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
662 self.logical_device_id, device.serial_number,
663 grouped=True, freq_override=False, **kwargs)
664 pm_config = self._pm_metrics.make_proto()
665 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
666 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
667 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
668
669 # Note, ONU ID and UNI intf set in add_uni_port method
670 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
671 ani_ports=[self._pon])
672
673 # Code to Run OMCI Test Action
674 kwargs_omci_test_action = {
675 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
676 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
677 }
678 serial_number = device.serial_number
679 self._test_request = OmciTestRequest(self.core_proxy,
680 self.omci_agent, self.device_id,
681 AniG, serial_number,
682 self.logical_device_id,
683 exclusive=False,
684 **kwargs_omci_test_action)
685
686 self.enabled = True
687 else:
688 self.logger.info('onu-already-activated')
689 */
690 logger.Debug("postInit-done")
691}
692
693// doStateConnected get the device info and update to voltha core
694// for comparison of the original method (not that easy to uncomment): compare here:
695// voltha-openolt-adapter/adaptercore/device_handler.go
696// -> this one obviously initiates all communication interfaces of the device ...?
697func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
698
699 logger.Debug("doStateConnected-started")
700 var err error
701 err = errors.New("Device FSM: function not implemented yet!")
702 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000703 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700704 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000705}
706
707// doStateUp handle the onu up indication and update to voltha core
708func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
709
710 logger.Debug("doStateUp-started")
711 var err error
712 err = errors.New("Device FSM: function not implemented yet!")
713 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000714 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700715 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000716
717 /*
718 // Synchronous call to update device state - this method is run in its own go routine
719 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
720 voltha.OperStatus_ACTIVE); err != nil {
721 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
722 return err
723 }
724 return nil
725 */
726}
727
728// doStateDown handle the onu down indication
729func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
730
731 logger.Debug("doStateDown-started")
732 var err error
733
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000734 device := dh.device
735 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000736 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000737 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000738 e.Cancel(err)
739 return
740 }
741
742 cloned := proto.Clone(device).(*voltha.Device)
743 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
744 /*
745 // Update the all ports state on that device to disable
746 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
747 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
748 return er
749 }
750
751 //Update the device oper state and connection status
752 cloned.OperStatus = voltha.OperStatus_UNKNOWN
753 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
754 dh.device = cloned
755
756 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
757 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
758 return er
759 }
760
761 //get the child device for the parent device
762 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
763 if err != nil {
764 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
765 return err
766 }
767 for _, onuDevice := range onuDevices.Items {
768
769 // Update onu state as down in onu adapter
770 onuInd := oop.OnuIndication{}
771 onuInd.OperState = "down"
772 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
773 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
774 if er != nil {
775 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
776 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
777 //Do not return here and continue to process other ONUs
778 }
779 }
780 // * Discovered ONUs entries need to be cleared , since after OLT
781 // is up, it starts sending discovery indications again* /
782 dh.discOnus = sync.Map{}
783 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
784 return nil
785 */
786 err = errors.New("Device FSM: function not implemented yet!")
787 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000788 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700789 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000790}
791
792// DeviceHandler StateMachine related state transition methods ##### end #########
793// #################################################################################
794
795// ###################################################
796// DeviceHandler utility methods ##### begin #########
797
mpagenko3af1f032020-06-10 08:53:41 +0000798//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
799func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
800 dh.lockDevice.RLock()
801 pOnuDeviceEntry := dh.pOnuOmciDevice
802 if aWait && pOnuDeviceEntry == nil {
803 //keep the read sema short to allow for subsequent write
804 dh.lockDevice.RUnlock()
805 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"deviceID": dh.deviceID})
806 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
807 // so it might be needed to wait here for that event with some timeout
808 select {
809 case <-time.After(60 * time.Second): //timer may be discussed ...
810 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"deviceID": dh.deviceID})
811 return nil
812 case <-dh.deviceEntrySet:
813 logger.Debugw("devicEntry ready now - continue", log.Fields{"deviceID": dh.deviceID})
814 // if written now, we can return the written value without sema
815 return dh.pOnuOmciDevice
816 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000817 }
mpagenko3af1f032020-06-10 08:53:41 +0000818 dh.lockDevice.RUnlock()
819 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000820}
821
mpagenko3af1f032020-06-10 08:53:41 +0000822//SetOnuDeviceEntry sets the ONU device entry within the handler
mpagenkoaf801632020-07-03 10:00:42 +0000823func (dh *DeviceHandler) SetOnuDeviceEntry(
824 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000825 dh.lockDevice.Lock()
826 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000827 dh.pOnuOmciDevice = apDeviceEntry
828 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000829 return nil
830}
831
mpagenko3af1f032020-06-10 08:53:41 +0000832//AddOnuDeviceEntry creates a new ONU device or returns the existing
833func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000834 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
835
mpagenko3af1f032020-06-10 08:53:41 +0000836 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000837 if deviceEntry == nil {
838 /* costum_me_map in python code seems always to be None,
839 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
840 /* also no 'clock' argument - usage open ...*/
841 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000842 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
843 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000844 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000845 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000846 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000847 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000848 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000849 // fire deviceEntry ready event to spread to possibly waiting processing
850 dh.deviceEntrySet <- true
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000851 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
852 } else {
853 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
854 }
855 // might be updated with some error handling !!!
856 return nil
857}
858
859// doStateInit provides the device update to the core
860func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000861 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
862 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
863
864 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000865
mpagenko3af1f032020-06-10 08:53:41 +0000866 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
867 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000868 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
869 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000870 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
871 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
872 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
mpagenkoaf801632020-07-03 10:00:42 +0000873 // but I would not know why, and the go code anyway does not work with the device directly anymore in the OnuDeviceEntry
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000874 // so let's just try to keep it simple ...
875 /*
876 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
877 if err != nil || device == nil {
878 //TODO: needs to handle error scenarios
879 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
880 return errors.New("Voltha Device not found")
881 }
882 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000883
mpagenko3af1f032020-06-10 08:53:41 +0000884 pDevEntry := dh.GetOnuDeviceEntry(true)
885 if pDevEntry != nil {
886 pDevEntry.Start(context.TODO())
887 } else {
888 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
889 return errors.New("No valid OnuDevice")
890 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000891 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
892 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
893 }
mpagenko3af1f032020-06-10 08:53:41 +0000894 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000895
896 /* this might be a good time for Omci Verify message? */
897 verifyExec := make(chan bool)
898 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000899 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000900 true, true) //eclusive and allowFailure (anyway not yet checked)
901 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
902
903 /* give the handler some time here to wait for the OMCi verification result
904 after Timeout start and try MibUpload FSM anyway
905 (to prevent stopping on just not supported OMCI verification from ONU) */
906 select {
907 case <-time.After(2 * time.Second):
908 logger.Warn("omci start-verification timed out (continue normal)")
909 case testresult := <-verifyExec:
910 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
911 }
912
913 /* In py code it looks earlier (on activate ..)
914 # Code to Run OMCI Test Action
915 kwargs_omci_test_action = {
916 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
917 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
918 }
919 serial_number = device.serial_number
920 self._test_request = OmciTestRequest(self.core_proxy,
921 self.omci_agent, self.device_id,
922 AniG, serial_number,
923 self.logical_device_id,
924 exclusive=False,
925 **kwargs_omci_test_action)
926 ...
927 # Start test requests after a brief pause
928 if not self._test_request_started:
929 self._test_request_started = True
930 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
931 reactor.callLater(tststart, self._test_request.start_collector)
932
933 */
934 /* which is then: in omci_test_request.py : */
935 /*
936 def start_collector(self, callback=None):
937 """
938 Start the collection loop for an adapter if the frequency > 0
939
940 :param callback: (callable) Function to call to collect PM data
941 """
942 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
943 if callback is None:
944 callback = self.perform_test_omci
945
946 if self.lc is None:
947 self.lc = LoopingCall(callback)
948
949 if self.default_freq > 0:
950 self.lc.start(interval=self.default_freq / 10)
951
952 def perform_test_omci(self):
953 """
954 Perform the initial test request
955 """
956 ani_g_entities = self._device.configuration.ani_g_entities
957 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
958 is not None else None
959 self._entity_id = ani_g_entities_ids[0]
960 self.logger.info('perform-test', entity_class=self._entity_class,
961 entity_id=self._entity_id)
962 try:
963 frame = MEFrame(self._entity_class, self._entity_id, []).test()
964 result = yield self._device.omci_cc.send(frame)
965 if not result.fields['omci_message'].fields['success_code']:
966 self.logger.info('Self-Test Submitted Successfully',
967 code=result.fields[
968 'omci_message'].fields['success_code'])
969 else:
970 raise TestFailure('Test Failure: {}'.format(
971 result.fields['omci_message'].fields['success_code']))
972 except TimeoutError as e:
973 self.deferred.errback(failure.Failure(e))
974
975 except Exception as e:
976 self.logger.exception('perform-test-Error', e=e,
977 class_id=self._entity_class,
978 entity_id=self._entity_id)
979 self.deferred.errback(failure.Failure(e))
980
981 */
982
983 // PM related heartbeat??? !!!TODO....
984 //self._heartbeat.enabled = True
985
mpagenko1cc3cb42020-07-27 15:24:38 +0000986 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
987 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
988 * as further OltAdapter processing may rely on the deviceReason event 'MibUploadDone' as a result of the FSM processing
989 * otherwise some processing synchronisation would be required - cmp. e.g TechProfile processing
990 */
991 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +0000992 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000993 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000994 if pMibUlFsm.Is(ulStDisabled) {
995 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000996 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
997 return errors.New("Can't go to state starting")
998 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000999 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001000 //Determine ONU status and start/re-start MIB Synchronization tasks
1001 //Determine if this ONU has ever synchronized
1002 if true { //TODO: insert valid check
mpagenko1cc3cb42020-07-27 15:24:38 +00001003 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001004 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
1005 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001006 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001007 } else {
mpagenko1cc3cb42020-07-27 15:24:38 +00001008 pMibUlFsm.Event(ulEvExamineMds)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001009 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001010 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001011 // callbacks to be handled:
mpagenko1cc3cb42020-07-27 15:24:38 +00001012 // Event(ulEvSuccess)
1013 // Event(ulEvTimeout)
1014 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001015 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001016 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001017 } else {
1018 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
1019 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001020 }
1021 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001022 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001023 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001024 }
1025 return nil
1026}
1027
mpagenko3af1f032020-06-10 08:53:41 +00001028func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
1029 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
1030 if dh.deviceReason != "stopping-openomci" {
1031 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"deviceID": dh.deviceID})
1032 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
1033 pDevEntry := dh.GetOnuDeviceEntry(false)
1034 if pDevEntry == nil {
1035 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1036 return errors.New("No valid OnuDevice")
1037 }
1038
1039 switch dh.deviceReason {
1040 case "starting-openomci":
1041 { //MIBSync FSM may run
1042 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
1043 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001044 pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +00001045 }
1046 }
1047 case "discovery-mibsync-complete":
1048 { //MibDownload may run
1049 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1050 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001051 pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001052 }
1053 }
1054 default:
mpagenko3dbcdd22020-07-22 07:38:45 +00001055 {
1056 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +00001057 if dh.pUnlockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001058 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001059 }
1060 if dh.pLockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001061 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001062 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001063 //techProfile related PonAniConfigFsm FSM may be active
1064 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
1065 if dh.pOnuTP.pAniConfigFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001066 dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +00001067 }
mpagenko3af1f032020-06-10 08:53:41 +00001068 }
1069 //TODO!!! care about PM/Alarm processing once started
1070 }
1071 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
1072 // (mainly the still seperate 'Event states')
1073 // so it is questionable, how this is resolved after some possible re-enable
1074 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1075
1076 //stop/remove(?) the device entry
1077 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
1078
1079 //TODO!!! remove existing traffic profiles
1080 /* from py code, if TP's exist, remove them - not yet implemented
1081 self._tp = dict()
1082 # Let TP download happen again
1083 for uni_id in self._tp_service_specific_task:
1084 self._tp_service_specific_task[uni_id].clear()
1085 for uni_id in self._tech_profile_download_done:
1086 self._tech_profile_download_done[uni_id].clear()
1087 */
1088
1089 dh.disableUniPortStateUpdate()
1090
1091 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
1092 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
1093 log.Fields{"deviceID": dh.deviceID, "error": err})
1094 // abort: system behavior is just unstable ...
1095 return err
1096 }
1097 dh.deviceReason = "stopping-openomci"
1098
1099 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1100 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
1101 logger.Errorw("error-updating-device-state unreachable-discovered",
1102 log.Fields{"deviceID": dh.deviceID, "error": err})
1103 // abort: system behavior is just unstable ...
1104 return err
1105 }
1106 } else {
1107 logger.Debugw("updateInterface - device already stopped", log.Fields{"deviceID": dh.deviceID})
1108 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001109 return nil
1110}
1111
mpagenko3af1f032020-06-10 08:53:41 +00001112//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001113func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
1114 switch dev_Event {
1115 case MibDatabaseSync:
1116 {
mpagenko3dbcdd22020-07-22 07:38:45 +00001117 logger.Debugw("MibInSync event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001118 //initiate DevStateUpdate
1119 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1120 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1121 "deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001122 } else {
1123 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001124 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001125 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001126 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001127
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001128 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001129 pDevEntry := dh.GetOnuDeviceEntry(false)
1130 if unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001131 for _, mgmtEntityId := range unigInstKeys {
1132 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1133 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
1134 dh.addUniPort(mgmtEntityId, i, UniPPTP)
1135 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001136 }
1137 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001138 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001139 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001140 if veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001141 for _, mgmtEntityId := range veipInstKeys {
1142 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1143 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
1144 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1145 i++
1146 }
1147 } else {
1148 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
1149 }
1150 if i == 0 {
1151 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
1152 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001153
mpagenko3af1f032020-06-10 08:53:41 +00001154 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1155 * left the code here as comment in case such processing should prove needed unexpectedly
1156 // Init Uni Ports to Admin locked state
1157 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1158 // *** should generate UniLockStateDone event *****
1159 if dh.pLockStateFsm == nil {
1160 dh.createUniLockFsm(true, UniLockStateDone)
1161 } else { //LockStateFSM already init
1162 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1163 dh.runUniLockFsm(true)
1164 }
1165 }
1166 case UniLockStateDone:
1167 {
1168 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
1169 * lockState processing commented out
1170 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001171 /* Mib download procedure -
1172 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1173 */
mpagenko3af1f032020-06-10 08:53:41 +00001174 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001175 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001176 if pMibDlFsm.Is(dlStDisabled) {
1177 if err := pMibDlFsm.Event(dlEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001178 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1179 // maybe try a FSM reset and then again ... - TODO!!!
1180 } else {
1181 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1182 // maybe use more specific states here for the specific download steps ...
mpagenko1cc3cb42020-07-27 15:24:38 +00001183 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001184 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1185 } else {
1186 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1187 //Begin MIB data download (running autonomously)
1188 }
1189 }
1190 } else {
1191 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1192 // maybe try a FSM reset and then again ... - TODO!!!
1193 }
1194 /***** Mib download started */
1195 } else {
1196 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1197 }
1198 }
1199 case MibDownloadDone:
1200 {
mpagenko3dbcdd22020-07-22 07:38:45 +00001201 logger.Debugw("MibDownloadDone event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001202 //initiate DevStateUpdate
1203 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1204 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1205 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001206 } else {
1207 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001208 }
mpagenko3af1f032020-06-10 08:53:41 +00001209
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001210 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1211 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1212 log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001213 } else {
1214 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001215 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001216 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001217 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001218 // *** should generate UniUnlockStateDone event *****
1219 if dh.pUnlockStateFsm == nil {
1220 dh.createUniLockFsm(false, UniUnlockStateDone)
1221 } else { //UnlockStateFSM already init
1222 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1223 dh.runUniLockFsm(false)
1224 }
1225 }
1226 case UniUnlockStateDone:
1227 {
mpagenko3af1f032020-06-10 08:53:41 +00001228 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001229
1230 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
1231 raisedTs := time.Now().UnixNano()
1232 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1233 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001234 case OmciAniConfigDone:
1235 {
1236 logger.Debugw("OmciAniConfigDone event received", log.Fields{"deviceID": dh.deviceID})
1237 //TODO!: it might be needed to check some 'cached' pending flow configuration (vlan setting)
1238 // - to consider with outstanding flow implementation
1239 // attention: the device reason update is done based on ONU-UNI-Port related activity
1240 // - which may cause some inconsistency
1241 if dh.deviceReason != "tech-profile-config-download-success" {
1242 // which may be the case from some previous actvity on another UNI Port of the ONU
1243 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1244 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1245 log.Fields{"deviceID": dh.deviceID, "error": err})
1246 } else {
1247 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1248 log.Fields{"deviceID": dh.deviceID})
1249 }
1250 //set internal state anyway - as it was done
1251 dh.deviceReason = "tech-profile-config-download-success"
1252 }
1253 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001254 default:
1255 {
1256 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
1257 }
1258 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001259}
1260
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001261func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001262 // parameters are IntfId, OnuId, uniId
1263 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1264 uint32(a_uniId))
1265 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001266 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1267 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001268 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001269 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001270 if pUniPort == nil {
1271 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1272 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001273 //store UniPort with the System-PortNumber key
1274 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001275 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001276 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1277 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1278 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001279 }
1280 }
1281}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001282
mpagenko3af1f032020-06-10 08:53:41 +00001283// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1284func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001285 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1286 // but towards core only the first port active state is signalled
1287 // with following remark:
1288 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1289 // # load on the core
1290
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001291 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001292
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001293 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001294 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001295 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1296 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1297 uniPort.SetOperState(vc.OperStatus_ACTIVE)
1298 //maybe also use getter functions on uniPort - perhaps later ...
mpagenko3af1f032020-06-10 08:53:41 +00001299 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1300 }
1301 }
1302}
1303
1304// Disable UniPortState and update core port state accordingly
1305func (dh *DeviceHandler) disableUniPortStateUpdate() {
1306 // compare enableUniPortStateUpdate() above
1307 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1308 for uniNo, uniPort := range dh.uniEntityMap {
1309 // only if this port is validated for operState transfer
1310 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1311 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1312 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1313 //maybe also use getter functions on uniPort - perhaps later ...
1314 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001315 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001316 }
1317}
1318
1319// ONU_Active/Inactive announcement on system KAFKA bus
1320// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1321func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1322 var de voltha.DeviceEvent
1323 eventContext := make(map[string]string)
1324 //Populating event context
1325 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1326 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1327 if err != nil || parentDevice == nil {
1328 logger.Errorw("Failed to fetch parent device for OnuEvent",
1329 log.Fields{"parentId": dh.parentId, "err": err})
1330 }
1331 oltSerialNumber := parentDevice.SerialNumber
1332
1333 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1334 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1335 eventContext["serial-number"] = dh.device.SerialNumber
1336 eventContext["olt_serial_number"] = oltSerialNumber
1337 eventContext["device_id"] = a_deviceID
1338 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1339 logger.Debugw("prepare ONU_ACTIVATED event",
1340 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1341
1342 /* Populating device event body */
1343 de.Context = eventContext
1344 de.ResourceId = a_deviceID
1345 if a_OperState == voltha.OperStatus_ACTIVE {
1346 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1347 de.Description = fmt.Sprintf("%s Event - %s - %s",
1348 cEventObjectType, cOnuActivatedEvent, "Raised")
1349 } else {
1350 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1351 de.Description = fmt.Sprintf("%s Event - %s - %s",
1352 cEventObjectType, cOnuActivatedEvent, "Cleared")
1353 }
1354 /* Send event to KAFKA */
1355 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1356 logger.Warnw("could not send ONU_ACTIVATED event",
1357 log.Fields{"DeviceId": a_deviceID, "error": err})
1358 }
1359 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1360 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1361}
1362
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001363// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1364func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1365 chLSFsm := make(chan Message, 2048)
1366 var sFsmName string
1367 if aAdminState == true {
1368 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1369 sFsmName = "LockStateFSM"
1370 } else {
1371 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1372 sFsmName = "UnLockStateFSM"
1373 }
mpagenko3af1f032020-06-10 08:53:41 +00001374
1375 pDevEntry := dh.GetOnuDeviceEntry(true)
1376 if pDevEntry == nil {
1377 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1378 return
1379 }
1380 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001381 sFsmName, dh.deviceID, chLSFsm)
1382 if pLSFsm != nil {
1383 if aAdminState == true {
1384 dh.pLockStateFsm = pLSFsm
1385 } else {
1386 dh.pUnlockStateFsm = pLSFsm
1387 }
1388 dh.runUniLockFsm(aAdminState)
1389 } else {
1390 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1391 }
1392}
1393
1394// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1395func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1396 /* Uni Port lock/unlock procedure -
1397 ***** should run via 'adminDone' state and generate the argument requested event *****
1398 */
1399 var pLSStatemachine *fsm.FSM
1400 if aAdminState == true {
1401 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1402 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1403 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001404 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1405 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001406 }
1407 } else {
1408 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1409 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1410 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001411 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1412 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001413 }
1414 }
1415 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001416 if pLSStatemachine.Is(uniStDisabled) {
1417 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001418 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1419 // maybe try a FSM reset and then again ... - TODO!!!
1420 } else {
1421 /***** LockStateFSM started */
1422 logger.Debugw("LockStateFSM started", log.Fields{
1423 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1424 }
1425 } else {
1426 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1427 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1428 // maybe try a FSM reset and then again ... - TODO!!!
1429 }
1430 } else {
1431 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1432 // maybe try a FSM reset and then again ... - TODO!!!
1433 }
1434}
1435
mpagenkoaf801632020-07-03 10:00:42 +00001436//SetBackend provides a DB backend for the specified path on the existing KV client
1437func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1438 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1439 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
1440 "BasePathKvStore": aBasePathKvStore, "deviceId": dh.deviceID})
1441 kvbackend := &db.Backend{
1442 Client: dh.pOpenOnuAc.kvClient,
1443 StoreType: dh.pOpenOnuAc.KVStoreType,
1444 /* address config update acc. to [VOL-2736] */
1445 Address: addr,
1446 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1447 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001448
mpagenkoaf801632020-07-03 10:00:42 +00001449 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001450}