blob: d1cb6f38923ab1b8edae00edeb5764873269294f [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
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000496// DeviceHandler methods that implement the adapters interface requests## end #########
497// #####################################################################################
498
499// ################ to be updated acc. needs of ONU Device ########################
500// DeviceHandler StateMachine related state transition methods ##### begin #########
501
502func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
503 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})
504}
505
506// doStateInit provides the device update to the core
507func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
508
509 logger.Debug("doStateInit-started")
510 var err error
511
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000512 // populate what we know. rest comes later after mib sync
513 dh.device.Root = false
514 dh.device.Vendor = "OpenONU"
515 dh.device.Model = "go"
516 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000517 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000518
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000519 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000520 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
521
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000522 dh.parentId = dh.device.ParentId
523 dh.ponPortNumber = dh.device.ParentPortNo
524
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000525 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
526 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
527 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
528 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
529 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000530 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000531
532 /*
533 self._pon = PonPort.create(self, self._pon_port_number)
534 self._pon.add_peer(self.parent_id, self._pon_port_number)
535 self.logger.debug('adding-pon-port-to-agent',
536 type=self._pon.get_port().type,
537 admin_state=self._pon.get_port().admin_state,
538 oper_status=self._pon.get_port().oper_status,
539 )
540 */
541 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000542 var ponPortNo uint32 = 1
543 if dh.ponPortNumber != 0 {
544 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000545 }
546
547 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000548 PortNo: ponPortNo,
549 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000550 Type: voltha.Port_PON_ONU,
551 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000552 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
553 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000554 }
555 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
556 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
557 e.Cancel(err)
558 return
559 }
560 logger.Debug("doStateInit-done")
561}
562
563// postInit setups the DeviceEntry for the conerned device
564func (dh *DeviceHandler) postInit(e *fsm.Event) {
565
566 logger.Debug("postInit-started")
567 var err error
568 /*
569 dh.Client = oop.NewOpenoltClient(dh.clientCon)
570 dh.pTransitionMap.Handle(ctx, GrpcConnected)
571 return nil
572 */
mpagenko3af1f032020-06-10 08:53:41 +0000573 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
574 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000575 e.Cancel(err)
576 return
577 }
578
579 /*
580 ############################################################################
581 # Setup Alarm handler
582 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
583 device.serial_number)
584 ############################################################################
585 # Setup PM configuration for this device
586 # Pass in ONU specific options
587 kwargs = {
588 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
589 'heartbeat': self.heartbeat,
590 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
591 }
592 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
593 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
594 self.logical_device_id, device.serial_number,
595 grouped=True, freq_override=False, **kwargs)
596 pm_config = self._pm_metrics.make_proto()
597 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
598 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
599 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
600
601 # Note, ONU ID and UNI intf set in add_uni_port method
602 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
603 ani_ports=[self._pon])
604
605 # Code to Run OMCI Test Action
606 kwargs_omci_test_action = {
607 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
608 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
609 }
610 serial_number = device.serial_number
611 self._test_request = OmciTestRequest(self.core_proxy,
612 self.omci_agent, self.device_id,
613 AniG, serial_number,
614 self.logical_device_id,
615 exclusive=False,
616 **kwargs_omci_test_action)
617
618 self.enabled = True
619 else:
620 self.logger.info('onu-already-activated')
621 */
622 logger.Debug("postInit-done")
623}
624
625// doStateConnected get the device info and update to voltha core
626// for comparison of the original method (not that easy to uncomment): compare here:
627// voltha-openolt-adapter/adaptercore/device_handler.go
628// -> this one obviously initiates all communication interfaces of the device ...?
629func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
630
631 logger.Debug("doStateConnected-started")
632 var err error
633 err = errors.New("Device FSM: function not implemented yet!")
634 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000635 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700636 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000637}
638
639// doStateUp handle the onu up indication and update to voltha core
640func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
641
642 logger.Debug("doStateUp-started")
643 var err error
644 err = errors.New("Device FSM: function not implemented yet!")
645 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000646 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700647 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000648
649 /*
650 // Synchronous call to update device state - this method is run in its own go routine
651 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
652 voltha.OperStatus_ACTIVE); err != nil {
653 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
654 return err
655 }
656 return nil
657 */
658}
659
660// doStateDown handle the onu down indication
661func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
662
663 logger.Debug("doStateDown-started")
664 var err error
665
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000666 device := dh.device
667 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000668 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000669 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000670 e.Cancel(err)
671 return
672 }
673
674 cloned := proto.Clone(device).(*voltha.Device)
675 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
676 /*
677 // Update the all ports state on that device to disable
678 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
679 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
680 return er
681 }
682
683 //Update the device oper state and connection status
684 cloned.OperStatus = voltha.OperStatus_UNKNOWN
685 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
686 dh.device = cloned
687
688 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
689 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
690 return er
691 }
692
693 //get the child device for the parent device
694 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
695 if err != nil {
696 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
697 return err
698 }
699 for _, onuDevice := range onuDevices.Items {
700
701 // Update onu state as down in onu adapter
702 onuInd := oop.OnuIndication{}
703 onuInd.OperState = "down"
704 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
705 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
706 if er != nil {
707 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
708 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
709 //Do not return here and continue to process other ONUs
710 }
711 }
712 // * Discovered ONUs entries need to be cleared , since after OLT
713 // is up, it starts sending discovery indications again* /
714 dh.discOnus = sync.Map{}
715 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
716 return nil
717 */
718 err = errors.New("Device FSM: function not implemented yet!")
719 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000720 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700721 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000722}
723
724// DeviceHandler StateMachine related state transition methods ##### end #########
725// #################################################################################
726
727// ###################################################
728// DeviceHandler utility methods ##### begin #########
729
mpagenko3af1f032020-06-10 08:53:41 +0000730//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
731func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
732 dh.lockDevice.RLock()
733 pOnuDeviceEntry := dh.pOnuOmciDevice
734 if aWait && pOnuDeviceEntry == nil {
735 //keep the read sema short to allow for subsequent write
736 dh.lockDevice.RUnlock()
737 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"deviceID": dh.deviceID})
738 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
739 // so it might be needed to wait here for that event with some timeout
740 select {
741 case <-time.After(60 * time.Second): //timer may be discussed ...
742 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"deviceID": dh.deviceID})
743 return nil
744 case <-dh.deviceEntrySet:
745 logger.Debugw("devicEntry ready now - continue", log.Fields{"deviceID": dh.deviceID})
746 // if written now, we can return the written value without sema
747 return dh.pOnuOmciDevice
748 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000749 }
mpagenko3af1f032020-06-10 08:53:41 +0000750 dh.lockDevice.RUnlock()
751 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000752}
753
mpagenko3af1f032020-06-10 08:53:41 +0000754//SetOnuDeviceEntry sets the ONU device entry within the handler
mpagenkoaf801632020-07-03 10:00:42 +0000755func (dh *DeviceHandler) SetOnuDeviceEntry(
756 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000757 dh.lockDevice.Lock()
758 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000759 dh.pOnuOmciDevice = apDeviceEntry
760 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000761 return nil
762}
763
mpagenko3af1f032020-06-10 08:53:41 +0000764//AddOnuDeviceEntry creates a new ONU device or returns the existing
765func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000766 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
767
mpagenko3af1f032020-06-10 08:53:41 +0000768 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000769 if deviceEntry == nil {
770 /* costum_me_map in python code seems always to be None,
771 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
772 /* also no 'clock' argument - usage open ...*/
773 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000774 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
775 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000776 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000777 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000778 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000779 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000780 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000781 // fire deviceEntry ready event to spread to possibly waiting processing
782 dh.deviceEntrySet <- true
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000783 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
784 } else {
785 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
786 }
787 // might be updated with some error handling !!!
788 return nil
789}
790
791// doStateInit provides the device update to the core
792func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000793 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
794 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
795
796 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000797
mpagenko3af1f032020-06-10 08:53:41 +0000798 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
799 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000800 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
801 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000802 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
803 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
804 // 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 +0000805 // 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 +0000806 // so let's just try to keep it simple ...
807 /*
808 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
809 if err != nil || device == nil {
810 //TODO: needs to handle error scenarios
811 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
812 return errors.New("Voltha Device not found")
813 }
814 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000815
mpagenko3af1f032020-06-10 08:53:41 +0000816 pDevEntry := dh.GetOnuDeviceEntry(true)
817 if pDevEntry != nil {
818 pDevEntry.Start(context.TODO())
819 } else {
820 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
821 return errors.New("No valid OnuDevice")
822 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000823 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
824 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
825 }
mpagenko3af1f032020-06-10 08:53:41 +0000826 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000827
828 /* this might be a good time for Omci Verify message? */
829 verifyExec := make(chan bool)
830 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000831 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000832 true, true) //eclusive and allowFailure (anyway not yet checked)
833 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
834
835 /* give the handler some time here to wait for the OMCi verification result
836 after Timeout start and try MibUpload FSM anyway
837 (to prevent stopping on just not supported OMCI verification from ONU) */
838 select {
839 case <-time.After(2 * time.Second):
840 logger.Warn("omci start-verification timed out (continue normal)")
841 case testresult := <-verifyExec:
842 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
843 }
844
845 /* In py code it looks earlier (on activate ..)
846 # Code to Run OMCI Test Action
847 kwargs_omci_test_action = {
848 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
849 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
850 }
851 serial_number = device.serial_number
852 self._test_request = OmciTestRequest(self.core_proxy,
853 self.omci_agent, self.device_id,
854 AniG, serial_number,
855 self.logical_device_id,
856 exclusive=False,
857 **kwargs_omci_test_action)
858 ...
859 # Start test requests after a brief pause
860 if not self._test_request_started:
861 self._test_request_started = True
862 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
863 reactor.callLater(tststart, self._test_request.start_collector)
864
865 */
866 /* which is then: in omci_test_request.py : */
867 /*
868 def start_collector(self, callback=None):
869 """
870 Start the collection loop for an adapter if the frequency > 0
871
872 :param callback: (callable) Function to call to collect PM data
873 """
874 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
875 if callback is None:
876 callback = self.perform_test_omci
877
878 if self.lc is None:
879 self.lc = LoopingCall(callback)
880
881 if self.default_freq > 0:
882 self.lc.start(interval=self.default_freq / 10)
883
884 def perform_test_omci(self):
885 """
886 Perform the initial test request
887 """
888 ani_g_entities = self._device.configuration.ani_g_entities
889 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
890 is not None else None
891 self._entity_id = ani_g_entities_ids[0]
892 self.logger.info('perform-test', entity_class=self._entity_class,
893 entity_id=self._entity_id)
894 try:
895 frame = MEFrame(self._entity_class, self._entity_id, []).test()
896 result = yield self._device.omci_cc.send(frame)
897 if not result.fields['omci_message'].fields['success_code']:
898 self.logger.info('Self-Test Submitted Successfully',
899 code=result.fields[
900 'omci_message'].fields['success_code'])
901 else:
902 raise TestFailure('Test Failure: {}'.format(
903 result.fields['omci_message'].fields['success_code']))
904 except TimeoutError as e:
905 self.deferred.errback(failure.Failure(e))
906
907 except Exception as e:
908 self.logger.exception('perform-test-Error', e=e,
909 class_id=self._entity_class,
910 entity_id=self._entity_id)
911 self.deferred.errback(failure.Failure(e))
912
913 */
914
915 // PM related heartbeat??? !!!TODO....
916 //self._heartbeat.enabled = True
917
mpagenko1cc3cb42020-07-27 15:24:38 +0000918 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
919 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
920 * as further OltAdapter processing may rely on the deviceReason event 'MibUploadDone' as a result of the FSM processing
921 * otherwise some processing synchronisation would be required - cmp. e.g TechProfile processing
922 */
923 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +0000924 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000925 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000926 if pMibUlFsm.Is(ulStDisabled) {
927 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000928 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
929 return errors.New("Can't go to state starting")
930 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000931 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000932 //Determine ONU status and start/re-start MIB Synchronization tasks
933 //Determine if this ONU has ever synchronized
934 if true { //TODO: insert valid check
mpagenko1cc3cb42020-07-27 15:24:38 +0000935 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000936 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
937 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000938 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000939 } else {
mpagenko1cc3cb42020-07-27 15:24:38 +0000940 pMibUlFsm.Event(ulEvExamineMds)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000941 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000942 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000943 // callbacks to be handled:
mpagenko1cc3cb42020-07-27 15:24:38 +0000944 // Event(ulEvSuccess)
945 // Event(ulEvTimeout)
946 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000947 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000948 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000949 } else {
950 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
951 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000952 }
953 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000954 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000955 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000956 }
957 return nil
958}
959
mpagenko3af1f032020-06-10 08:53:41 +0000960func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
961 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
962 if dh.deviceReason != "stopping-openomci" {
963 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"deviceID": dh.deviceID})
964 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
965 pDevEntry := dh.GetOnuDeviceEntry(false)
966 if pDevEntry == nil {
967 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
968 return errors.New("No valid OnuDevice")
969 }
970
971 switch dh.deviceReason {
972 case "starting-openomci":
973 { //MIBSync FSM may run
974 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
975 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000976 pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +0000977 }
978 }
979 case "discovery-mibsync-complete":
980 { //MibDownload may run
981 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
982 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000983 pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +0000984 }
985 }
986 default:
mpagenko3dbcdd22020-07-22 07:38:45 +0000987 {
988 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +0000989 if dh.pUnlockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000990 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +0000991 }
992 if dh.pLockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000993 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +0000994 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000995 //techProfile related PonAniConfigFsm FSM may be active
996 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
997 if dh.pOnuTP.pAniConfigFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000998 dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000999 }
mpagenko3af1f032020-06-10 08:53:41 +00001000 }
1001 //TODO!!! care about PM/Alarm processing once started
1002 }
1003 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
1004 // (mainly the still seperate 'Event states')
1005 // so it is questionable, how this is resolved after some possible re-enable
1006 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1007
1008 //stop/remove(?) the device entry
1009 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
1010
1011 //TODO!!! remove existing traffic profiles
1012 /* from py code, if TP's exist, remove them - not yet implemented
1013 self._tp = dict()
1014 # Let TP download happen again
1015 for uni_id in self._tp_service_specific_task:
1016 self._tp_service_specific_task[uni_id].clear()
1017 for uni_id in self._tech_profile_download_done:
1018 self._tech_profile_download_done[uni_id].clear()
1019 */
1020
1021 dh.disableUniPortStateUpdate()
1022
1023 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
1024 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
1025 log.Fields{"deviceID": dh.deviceID, "error": err})
1026 // abort: system behavior is just unstable ...
1027 return err
1028 }
1029 dh.deviceReason = "stopping-openomci"
1030
1031 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1032 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
1033 logger.Errorw("error-updating-device-state unreachable-discovered",
1034 log.Fields{"deviceID": dh.deviceID, "error": err})
1035 // abort: system behavior is just unstable ...
1036 return err
1037 }
1038 } else {
1039 logger.Debugw("updateInterface - device already stopped", log.Fields{"deviceID": dh.deviceID})
1040 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001041 return nil
1042}
1043
mpagenko3af1f032020-06-10 08:53:41 +00001044//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001045func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
1046 switch dev_Event {
1047 case MibDatabaseSync:
1048 {
mpagenko3dbcdd22020-07-22 07:38:45 +00001049 logger.Debugw("MibInSync event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001050 //initiate DevStateUpdate
1051 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1052 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1053 "deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001054 } else {
1055 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001056 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001057 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001058 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001059
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001060 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001061 pDevEntry := dh.GetOnuDeviceEntry(false)
1062 if unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001063 for _, mgmtEntityId := range unigInstKeys {
1064 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1065 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
1066 dh.addUniPort(mgmtEntityId, i, UniPPTP)
1067 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001068 }
1069 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001070 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001071 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001072 if veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001073 for _, mgmtEntityId := range veipInstKeys {
1074 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1075 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
1076 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1077 i++
1078 }
1079 } else {
1080 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
1081 }
1082 if i == 0 {
1083 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
1084 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001085
mpagenko3af1f032020-06-10 08:53:41 +00001086 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1087 * left the code here as comment in case such processing should prove needed unexpectedly
1088 // Init Uni Ports to Admin locked state
1089 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1090 // *** should generate UniLockStateDone event *****
1091 if dh.pLockStateFsm == nil {
1092 dh.createUniLockFsm(true, UniLockStateDone)
1093 } else { //LockStateFSM already init
1094 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1095 dh.runUniLockFsm(true)
1096 }
1097 }
1098 case UniLockStateDone:
1099 {
1100 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
1101 * lockState processing commented out
1102 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001103 /* Mib download procedure -
1104 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1105 */
mpagenko3af1f032020-06-10 08:53:41 +00001106 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001107 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001108 if pMibDlFsm.Is(dlStDisabled) {
1109 if err := pMibDlFsm.Event(dlEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001110 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1111 // maybe try a FSM reset and then again ... - TODO!!!
1112 } else {
1113 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1114 // maybe use more specific states here for the specific download steps ...
mpagenko1cc3cb42020-07-27 15:24:38 +00001115 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001116 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1117 } else {
1118 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1119 //Begin MIB data download (running autonomously)
1120 }
1121 }
1122 } else {
1123 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1124 // maybe try a FSM reset and then again ... - TODO!!!
1125 }
1126 /***** Mib download started */
1127 } else {
1128 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1129 }
1130 }
1131 case MibDownloadDone:
1132 {
mpagenko3dbcdd22020-07-22 07:38:45 +00001133 logger.Debugw("MibDownloadDone event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001134 //initiate DevStateUpdate
1135 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1136 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1137 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001138 } else {
1139 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001140 }
mpagenko3af1f032020-06-10 08:53:41 +00001141
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001142 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1143 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1144 log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001145 } else {
1146 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001147 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001148 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001149 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001150 // *** should generate UniUnlockStateDone event *****
1151 if dh.pUnlockStateFsm == nil {
1152 dh.createUniLockFsm(false, UniUnlockStateDone)
1153 } else { //UnlockStateFSM already init
1154 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1155 dh.runUniLockFsm(false)
1156 }
1157 }
1158 case UniUnlockStateDone:
1159 {
mpagenko3af1f032020-06-10 08:53:41 +00001160 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001161
1162 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
1163 raisedTs := time.Now().UnixNano()
1164 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1165 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001166 case OmciAniConfigDone:
1167 {
1168 logger.Debugw("OmciAniConfigDone event received", log.Fields{"deviceID": dh.deviceID})
1169 //TODO!: it might be needed to check some 'cached' pending flow configuration (vlan setting)
1170 // - to consider with outstanding flow implementation
1171 // attention: the device reason update is done based on ONU-UNI-Port related activity
1172 // - which may cause some inconsistency
1173 if dh.deviceReason != "tech-profile-config-download-success" {
1174 // which may be the case from some previous actvity on another UNI Port of the ONU
1175 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1176 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1177 log.Fields{"deviceID": dh.deviceID, "error": err})
1178 } else {
1179 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1180 log.Fields{"deviceID": dh.deviceID})
1181 }
1182 //set internal state anyway - as it was done
1183 dh.deviceReason = "tech-profile-config-download-success"
1184 }
1185 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001186 default:
1187 {
1188 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
1189 }
1190 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001191}
1192
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001193func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001194 // parameters are IntfId, OnuId, uniId
1195 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1196 uint32(a_uniId))
1197 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001198 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1199 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001200 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001201 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001202 if pUniPort == nil {
1203 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1204 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001205 //store UniPort with the System-PortNumber key
1206 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001207 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001208 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1209 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1210 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001211 }
1212 }
1213}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001214
mpagenko3af1f032020-06-10 08:53:41 +00001215// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1216func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001217 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1218 // but towards core only the first port active state is signalled
1219 // with following remark:
1220 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1221 // # load on the core
1222
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001223 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001224
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001225 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001226 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001227 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1228 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1229 uniPort.SetOperState(vc.OperStatus_ACTIVE)
1230 //maybe also use getter functions on uniPort - perhaps later ...
mpagenko3af1f032020-06-10 08:53:41 +00001231 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1232 }
1233 }
1234}
1235
1236// Disable UniPortState and update core port state accordingly
1237func (dh *DeviceHandler) disableUniPortStateUpdate() {
1238 // compare enableUniPortStateUpdate() above
1239 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1240 for uniNo, uniPort := range dh.uniEntityMap {
1241 // only if this port is validated for operState transfer
1242 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1243 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1244 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1245 //maybe also use getter functions on uniPort - perhaps later ...
1246 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001247 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001248 }
1249}
1250
1251// ONU_Active/Inactive announcement on system KAFKA bus
1252// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1253func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1254 var de voltha.DeviceEvent
1255 eventContext := make(map[string]string)
1256 //Populating event context
1257 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1258 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1259 if err != nil || parentDevice == nil {
1260 logger.Errorw("Failed to fetch parent device for OnuEvent",
1261 log.Fields{"parentId": dh.parentId, "err": err})
1262 }
1263 oltSerialNumber := parentDevice.SerialNumber
1264
1265 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1266 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1267 eventContext["serial-number"] = dh.device.SerialNumber
1268 eventContext["olt_serial_number"] = oltSerialNumber
1269 eventContext["device_id"] = a_deviceID
1270 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1271 logger.Debugw("prepare ONU_ACTIVATED event",
1272 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1273
1274 /* Populating device event body */
1275 de.Context = eventContext
1276 de.ResourceId = a_deviceID
1277 if a_OperState == voltha.OperStatus_ACTIVE {
1278 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1279 de.Description = fmt.Sprintf("%s Event - %s - %s",
1280 cEventObjectType, cOnuActivatedEvent, "Raised")
1281 } else {
1282 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1283 de.Description = fmt.Sprintf("%s Event - %s - %s",
1284 cEventObjectType, cOnuActivatedEvent, "Cleared")
1285 }
1286 /* Send event to KAFKA */
1287 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1288 logger.Warnw("could not send ONU_ACTIVATED event",
1289 log.Fields{"DeviceId": a_deviceID, "error": err})
1290 }
1291 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1292 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1293}
1294
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001295// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1296func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1297 chLSFsm := make(chan Message, 2048)
1298 var sFsmName string
1299 if aAdminState == true {
1300 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1301 sFsmName = "LockStateFSM"
1302 } else {
1303 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1304 sFsmName = "UnLockStateFSM"
1305 }
mpagenko3af1f032020-06-10 08:53:41 +00001306
1307 pDevEntry := dh.GetOnuDeviceEntry(true)
1308 if pDevEntry == nil {
1309 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1310 return
1311 }
1312 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001313 sFsmName, dh.deviceID, chLSFsm)
1314 if pLSFsm != nil {
1315 if aAdminState == true {
1316 dh.pLockStateFsm = pLSFsm
1317 } else {
1318 dh.pUnlockStateFsm = pLSFsm
1319 }
1320 dh.runUniLockFsm(aAdminState)
1321 } else {
1322 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1323 }
1324}
1325
1326// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1327func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1328 /* Uni Port lock/unlock procedure -
1329 ***** should run via 'adminDone' state and generate the argument requested event *****
1330 */
1331 var pLSStatemachine *fsm.FSM
1332 if aAdminState == true {
1333 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1334 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1335 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001336 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1337 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001338 }
1339 } else {
1340 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1341 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1342 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001343 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1344 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001345 }
1346 }
1347 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001348 if pLSStatemachine.Is(uniStDisabled) {
1349 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001350 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1351 // maybe try a FSM reset and then again ... - TODO!!!
1352 } else {
1353 /***** LockStateFSM started */
1354 logger.Debugw("LockStateFSM started", log.Fields{
1355 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1356 }
1357 } else {
1358 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1359 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1360 // maybe try a FSM reset and then again ... - TODO!!!
1361 }
1362 } else {
1363 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1364 // maybe try a FSM reset and then again ... - TODO!!!
1365 }
1366}
1367
mpagenkoaf801632020-07-03 10:00:42 +00001368//SetBackend provides a DB backend for the specified path on the existing KV client
1369func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1370 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1371 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
1372 "BasePathKvStore": aBasePathKvStore, "deviceId": dh.deviceID})
1373 kvbackend := &db.Backend{
1374 Client: dh.pOpenOnuAc.kvClient,
1375 StoreType: dh.pOpenOnuAc.KVStoreType,
1376 /* address config update acc. to [VOL-2736] */
1377 Address: addr,
1378 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1379 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001380
mpagenkoaf801632020-07-03 10:00:42 +00001381 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001382}