blob: a5805307f5bb7ab58bee26f29747a9c6d10ab56b [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()
mpagenko1cc3cb42020-07-27 15:24:38 +0000328 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collet their result
329 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 Hildebrandt0f9b88d2020-04-20 13:33:25 +0000478// DeviceHandler methods that implement the adapters interface requests## end #########
479// #####################################################################################
480
481// ################ to be updated acc. needs of ONU Device ########################
482// DeviceHandler StateMachine related state transition methods ##### begin #########
483
484func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
485 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})
486}
487
488// doStateInit provides the device update to the core
489func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
490
491 logger.Debug("doStateInit-started")
492 var err error
493
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000494 // populate what we know. rest comes later after mib sync
495 dh.device.Root = false
496 dh.device.Vendor = "OpenONU"
497 dh.device.Model = "go"
498 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000499 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000500
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000501 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000502 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
503
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000504 dh.parentId = dh.device.ParentId
505 dh.ponPortNumber = dh.device.ParentPortNo
506
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000507 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
508 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
509 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
510 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
511 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000512 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000513
514 /*
515 self._pon = PonPort.create(self, self._pon_port_number)
516 self._pon.add_peer(self.parent_id, self._pon_port_number)
517 self.logger.debug('adding-pon-port-to-agent',
518 type=self._pon.get_port().type,
519 admin_state=self._pon.get_port().admin_state,
520 oper_status=self._pon.get_port().oper_status,
521 )
522 */
523 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000524 var ponPortNo uint32 = 1
525 if dh.ponPortNumber != 0 {
526 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000527 }
528
529 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000530 PortNo: ponPortNo,
531 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000532 Type: voltha.Port_PON_ONU,
533 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000534 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
535 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000536 }
537 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
538 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
539 e.Cancel(err)
540 return
541 }
542 logger.Debug("doStateInit-done")
543}
544
545// postInit setups the DeviceEntry for the conerned device
546func (dh *DeviceHandler) postInit(e *fsm.Event) {
547
548 logger.Debug("postInit-started")
549 var err error
550 /*
551 dh.Client = oop.NewOpenoltClient(dh.clientCon)
552 dh.pTransitionMap.Handle(ctx, GrpcConnected)
553 return nil
554 */
mpagenko3af1f032020-06-10 08:53:41 +0000555 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
556 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000557 e.Cancel(err)
558 return
559 }
560
561 /*
562 ############################################################################
563 # Setup Alarm handler
564 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
565 device.serial_number)
566 ############################################################################
567 # Setup PM configuration for this device
568 # Pass in ONU specific options
569 kwargs = {
570 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
571 'heartbeat': self.heartbeat,
572 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
573 }
574 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
575 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
576 self.logical_device_id, device.serial_number,
577 grouped=True, freq_override=False, **kwargs)
578 pm_config = self._pm_metrics.make_proto()
579 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
580 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
581 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
582
583 # Note, ONU ID and UNI intf set in add_uni_port method
584 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
585 ani_ports=[self._pon])
586
587 # Code to Run OMCI Test Action
588 kwargs_omci_test_action = {
589 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
590 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
591 }
592 serial_number = device.serial_number
593 self._test_request = OmciTestRequest(self.core_proxy,
594 self.omci_agent, self.device_id,
595 AniG, serial_number,
596 self.logical_device_id,
597 exclusive=False,
598 **kwargs_omci_test_action)
599
600 self.enabled = True
601 else:
602 self.logger.info('onu-already-activated')
603 */
604 logger.Debug("postInit-done")
605}
606
607// doStateConnected get the device info and update to voltha core
608// for comparison of the original method (not that easy to uncomment): compare here:
609// voltha-openolt-adapter/adaptercore/device_handler.go
610// -> this one obviously initiates all communication interfaces of the device ...?
611func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
612
613 logger.Debug("doStateConnected-started")
614 var err error
615 err = errors.New("Device FSM: function not implemented yet!")
616 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000617 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700618 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000619}
620
621// doStateUp handle the onu up indication and update to voltha core
622func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
623
624 logger.Debug("doStateUp-started")
625 var err error
626 err = errors.New("Device FSM: function not implemented yet!")
627 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000628 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700629 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000630
631 /*
632 // Synchronous call to update device state - this method is run in its own go routine
633 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
634 voltha.OperStatus_ACTIVE); err != nil {
635 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
636 return err
637 }
638 return nil
639 */
640}
641
642// doStateDown handle the onu down indication
643func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
644
645 logger.Debug("doStateDown-started")
646 var err error
647
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000648 device := dh.device
649 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000650 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000651 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000652 e.Cancel(err)
653 return
654 }
655
656 cloned := proto.Clone(device).(*voltha.Device)
657 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
658 /*
659 // Update the all ports state on that device to disable
660 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
661 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
662 return er
663 }
664
665 //Update the device oper state and connection status
666 cloned.OperStatus = voltha.OperStatus_UNKNOWN
667 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
668 dh.device = cloned
669
670 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
671 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
672 return er
673 }
674
675 //get the child device for the parent device
676 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
677 if err != nil {
678 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
679 return err
680 }
681 for _, onuDevice := range onuDevices.Items {
682
683 // Update onu state as down in onu adapter
684 onuInd := oop.OnuIndication{}
685 onuInd.OperState = "down"
686 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
687 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
688 if er != nil {
689 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
690 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
691 //Do not return here and continue to process other ONUs
692 }
693 }
694 // * Discovered ONUs entries need to be cleared , since after OLT
695 // is up, it starts sending discovery indications again* /
696 dh.discOnus = sync.Map{}
697 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
698 return nil
699 */
700 err = errors.New("Device FSM: function not implemented yet!")
701 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000702 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700703 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000704}
705
706// DeviceHandler StateMachine related state transition methods ##### end #########
707// #################################################################################
708
709// ###################################################
710// DeviceHandler utility methods ##### begin #########
711
mpagenko3af1f032020-06-10 08:53:41 +0000712//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
713func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
714 dh.lockDevice.RLock()
715 pOnuDeviceEntry := dh.pOnuOmciDevice
716 if aWait && pOnuDeviceEntry == nil {
717 //keep the read sema short to allow for subsequent write
718 dh.lockDevice.RUnlock()
719 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"deviceID": dh.deviceID})
720 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
721 // so it might be needed to wait here for that event with some timeout
722 select {
723 case <-time.After(60 * time.Second): //timer may be discussed ...
724 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"deviceID": dh.deviceID})
725 return nil
726 case <-dh.deviceEntrySet:
727 logger.Debugw("devicEntry ready now - continue", log.Fields{"deviceID": dh.deviceID})
728 // if written now, we can return the written value without sema
729 return dh.pOnuOmciDevice
730 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000731 }
mpagenko3af1f032020-06-10 08:53:41 +0000732 dh.lockDevice.RUnlock()
733 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000734}
735
mpagenko3af1f032020-06-10 08:53:41 +0000736//SetOnuDeviceEntry sets the ONU device entry within the handler
mpagenkoaf801632020-07-03 10:00:42 +0000737func (dh *DeviceHandler) SetOnuDeviceEntry(
738 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000739 dh.lockDevice.Lock()
740 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000741 dh.pOnuOmciDevice = apDeviceEntry
742 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000743 return nil
744}
745
mpagenko3af1f032020-06-10 08:53:41 +0000746//AddOnuDeviceEntry creates a new ONU device or returns the existing
747func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000748 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
749
mpagenko3af1f032020-06-10 08:53:41 +0000750 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000751 if deviceEntry == nil {
752 /* costum_me_map in python code seems always to be None,
753 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
754 /* also no 'clock' argument - usage open ...*/
755 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000756 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
757 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000758 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000759 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000760 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000761 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000762 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000763 // fire deviceEntry ready event to spread to possibly waiting processing
764 dh.deviceEntrySet <- true
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000765 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
766 } else {
767 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
768 }
769 // might be updated with some error handling !!!
770 return nil
771}
772
773// doStateInit provides the device update to the core
774func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000775 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
776 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
777
778 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000779
mpagenko3af1f032020-06-10 08:53:41 +0000780 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
781 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000782 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
783 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000784 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
785 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
786 // 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 +0000787 // 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 +0000788 // so let's just try to keep it simple ...
789 /*
790 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
791 if err != nil || device == nil {
792 //TODO: needs to handle error scenarios
793 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
794 return errors.New("Voltha Device not found")
795 }
796 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000797
mpagenko3af1f032020-06-10 08:53:41 +0000798 pDevEntry := dh.GetOnuDeviceEntry(true)
799 if pDevEntry != nil {
800 pDevEntry.Start(context.TODO())
801 } else {
802 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
803 return errors.New("No valid OnuDevice")
804 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000805 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
806 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
807 }
mpagenko3af1f032020-06-10 08:53:41 +0000808 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000809
810 /* this might be a good time for Omci Verify message? */
811 verifyExec := make(chan bool)
812 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000813 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000814 true, true) //eclusive and allowFailure (anyway not yet checked)
815 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
816
817 /* give the handler some time here to wait for the OMCi verification result
818 after Timeout start and try MibUpload FSM anyway
819 (to prevent stopping on just not supported OMCI verification from ONU) */
820 select {
821 case <-time.After(2 * time.Second):
822 logger.Warn("omci start-verification timed out (continue normal)")
823 case testresult := <-verifyExec:
824 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
825 }
826
827 /* In py code it looks earlier (on activate ..)
828 # Code to Run OMCI Test Action
829 kwargs_omci_test_action = {
830 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
831 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
832 }
833 serial_number = device.serial_number
834 self._test_request = OmciTestRequest(self.core_proxy,
835 self.omci_agent, self.device_id,
836 AniG, serial_number,
837 self.logical_device_id,
838 exclusive=False,
839 **kwargs_omci_test_action)
840 ...
841 # Start test requests after a brief pause
842 if not self._test_request_started:
843 self._test_request_started = True
844 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
845 reactor.callLater(tststart, self._test_request.start_collector)
846
847 */
848 /* which is then: in omci_test_request.py : */
849 /*
850 def start_collector(self, callback=None):
851 """
852 Start the collection loop for an adapter if the frequency > 0
853
854 :param callback: (callable) Function to call to collect PM data
855 """
856 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
857 if callback is None:
858 callback = self.perform_test_omci
859
860 if self.lc is None:
861 self.lc = LoopingCall(callback)
862
863 if self.default_freq > 0:
864 self.lc.start(interval=self.default_freq / 10)
865
866 def perform_test_omci(self):
867 """
868 Perform the initial test request
869 """
870 ani_g_entities = self._device.configuration.ani_g_entities
871 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
872 is not None else None
873 self._entity_id = ani_g_entities_ids[0]
874 self.logger.info('perform-test', entity_class=self._entity_class,
875 entity_id=self._entity_id)
876 try:
877 frame = MEFrame(self._entity_class, self._entity_id, []).test()
878 result = yield self._device.omci_cc.send(frame)
879 if not result.fields['omci_message'].fields['success_code']:
880 self.logger.info('Self-Test Submitted Successfully',
881 code=result.fields[
882 'omci_message'].fields['success_code'])
883 else:
884 raise TestFailure('Test Failure: {}'.format(
885 result.fields['omci_message'].fields['success_code']))
886 except TimeoutError as e:
887 self.deferred.errback(failure.Failure(e))
888
889 except Exception as e:
890 self.logger.exception('perform-test-Error', e=e,
891 class_id=self._entity_class,
892 entity_id=self._entity_id)
893 self.deferred.errback(failure.Failure(e))
894
895 */
896
897 // PM related heartbeat??? !!!TODO....
898 //self._heartbeat.enabled = True
899
mpagenko1cc3cb42020-07-27 15:24:38 +0000900 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
901 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
902 * as further OltAdapter processing may rely on the deviceReason event 'MibUploadDone' as a result of the FSM processing
903 * otherwise some processing synchronisation would be required - cmp. e.g TechProfile processing
904 */
905 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +0000906 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000907 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000908 if pMibUlFsm.Is(ulStDisabled) {
909 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000910 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
911 return errors.New("Can't go to state starting")
912 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000913 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000914 //Determine ONU status and start/re-start MIB Synchronization tasks
915 //Determine if this ONU has ever synchronized
916 if true { //TODO: insert valid check
mpagenko1cc3cb42020-07-27 15:24:38 +0000917 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000918 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
919 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000920 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000921 } else {
mpagenko1cc3cb42020-07-27 15:24:38 +0000922 pMibUlFsm.Event(ulEvExamineMds)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000923 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000924 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000925 // callbacks to be handled:
mpagenko1cc3cb42020-07-27 15:24:38 +0000926 // Event(ulEvSuccess)
927 // Event(ulEvTimeout)
928 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000929 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000930 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000931 } else {
932 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
933 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000934 }
935 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000936 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000937 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000938 }
939 return nil
940}
941
mpagenko3af1f032020-06-10 08:53:41 +0000942func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
943 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
944 if dh.deviceReason != "stopping-openomci" {
945 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"deviceID": dh.deviceID})
946 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
947 pDevEntry := dh.GetOnuDeviceEntry(false)
948 if pDevEntry == nil {
949 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
950 return errors.New("No valid OnuDevice")
951 }
952
953 switch dh.deviceReason {
954 case "starting-openomci":
955 { //MIBSync FSM may run
956 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
957 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000958 pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +0000959 }
960 }
961 case "discovery-mibsync-complete":
962 { //MibDownload may run
963 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
964 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000965 pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +0000966 }
967 }
968 default:
mpagenko3dbcdd22020-07-22 07:38:45 +0000969 {
970 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +0000971 if dh.pUnlockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000972 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +0000973 }
974 if dh.pLockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000975 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +0000976 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000977 //techProfile related PonAniConfigFsm FSM may be active
978 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
979 if dh.pOnuTP.pAniConfigFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000980 dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000981 }
mpagenko3af1f032020-06-10 08:53:41 +0000982 }
983 //TODO!!! care about PM/Alarm processing once started
984 }
985 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
986 // (mainly the still seperate 'Event states')
987 // so it is questionable, how this is resolved after some possible re-enable
988 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
989
990 //stop/remove(?) the device entry
991 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
992
993 //TODO!!! remove existing traffic profiles
994 /* from py code, if TP's exist, remove them - not yet implemented
995 self._tp = dict()
996 # Let TP download happen again
997 for uni_id in self._tp_service_specific_task:
998 self._tp_service_specific_task[uni_id].clear()
999 for uni_id in self._tech_profile_download_done:
1000 self._tech_profile_download_done[uni_id].clear()
1001 */
1002
1003 dh.disableUniPortStateUpdate()
1004
1005 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
1006 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
1007 log.Fields{"deviceID": dh.deviceID, "error": err})
1008 // abort: system behavior is just unstable ...
1009 return err
1010 }
1011 dh.deviceReason = "stopping-openomci"
1012
1013 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1014 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
1015 logger.Errorw("error-updating-device-state unreachable-discovered",
1016 log.Fields{"deviceID": dh.deviceID, "error": err})
1017 // abort: system behavior is just unstable ...
1018 return err
1019 }
1020 } else {
1021 logger.Debugw("updateInterface - device already stopped", log.Fields{"deviceID": dh.deviceID})
1022 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001023 return nil
1024}
1025
mpagenko3af1f032020-06-10 08:53:41 +00001026//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001027func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
1028 switch dev_Event {
1029 case MibDatabaseSync:
1030 {
mpagenko3dbcdd22020-07-22 07:38:45 +00001031 logger.Debugw("MibInSync event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001032 //initiate DevStateUpdate
1033 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1034 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1035 "deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001036 } else {
1037 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001038 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001039 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001040 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001041
mpagenko3af1f032020-06-10 08:53:41 +00001042 pDevEntry := dh.GetOnuDeviceEntry(false)
1043 unigMap, ok := pDevEntry.pOnuDB.meDb[me.UniGClassID]
1044 unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(unigMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001045 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
1046 if ok {
1047 for _, mgmtEntityId := range unigInstKeys {
1048 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1049 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
1050 dh.addUniPort(mgmtEntityId, i, UniPPTP)
1051 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001052 }
1053 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001054 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001055 }
mpagenko3af1f032020-06-10 08:53:41 +00001056 veipMap, ok := pDevEntry.pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
1057 veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(veipMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001058 if ok {
1059 for _, mgmtEntityId := range veipInstKeys {
1060 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1061 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
1062 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1063 i++
1064 }
1065 } else {
1066 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
1067 }
1068 if i == 0 {
1069 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
1070 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001071
mpagenko3af1f032020-06-10 08:53:41 +00001072 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1073 * left the code here as comment in case such processing should prove needed unexpectedly
1074 // Init Uni Ports to Admin locked state
1075 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1076 // *** should generate UniLockStateDone event *****
1077 if dh.pLockStateFsm == nil {
1078 dh.createUniLockFsm(true, UniLockStateDone)
1079 } else { //LockStateFSM already init
1080 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1081 dh.runUniLockFsm(true)
1082 }
1083 }
1084 case UniLockStateDone:
1085 {
1086 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
1087 * lockState processing commented out
1088 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001089 /* Mib download procedure -
1090 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1091 */
mpagenko3af1f032020-06-10 08:53:41 +00001092 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001093 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001094 if pMibDlFsm.Is(dlStDisabled) {
1095 if err := pMibDlFsm.Event(dlEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001096 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1097 // maybe try a FSM reset and then again ... - TODO!!!
1098 } else {
1099 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1100 // maybe use more specific states here for the specific download steps ...
mpagenko1cc3cb42020-07-27 15:24:38 +00001101 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001102 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1103 } else {
1104 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1105 //Begin MIB data download (running autonomously)
1106 }
1107 }
1108 } else {
1109 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1110 // maybe try a FSM reset and then again ... - TODO!!!
1111 }
1112 /***** Mib download started */
1113 } else {
1114 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1115 }
1116 }
1117 case MibDownloadDone:
1118 {
mpagenko3dbcdd22020-07-22 07:38:45 +00001119 logger.Debugw("MibDownloadDone event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001120 //initiate DevStateUpdate
1121 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1122 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1123 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001124 } else {
1125 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001126 }
mpagenko3af1f032020-06-10 08:53:41 +00001127
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001128 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1129 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1130 log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001131 } else {
1132 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001133 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001134 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001135 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001136 // *** should generate UniUnlockStateDone event *****
1137 if dh.pUnlockStateFsm == nil {
1138 dh.createUniLockFsm(false, UniUnlockStateDone)
1139 } else { //UnlockStateFSM already init
1140 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1141 dh.runUniLockFsm(false)
1142 }
1143 }
1144 case UniUnlockStateDone:
1145 {
mpagenko3af1f032020-06-10 08:53:41 +00001146 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001147
1148 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
1149 raisedTs := time.Now().UnixNano()
1150 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1151 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001152 case OmciAniConfigDone:
1153 {
1154 logger.Debugw("OmciAniConfigDone event received", log.Fields{"deviceID": dh.deviceID})
1155 //TODO!: it might be needed to check some 'cached' pending flow configuration (vlan setting)
1156 // - to consider with outstanding flow implementation
1157 // attention: the device reason update is done based on ONU-UNI-Port related activity
1158 // - which may cause some inconsistency
1159 if dh.deviceReason != "tech-profile-config-download-success" {
1160 // which may be the case from some previous actvity on another UNI Port of the ONU
1161 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1162 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1163 log.Fields{"deviceID": dh.deviceID, "error": err})
1164 } else {
1165 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1166 log.Fields{"deviceID": dh.deviceID})
1167 }
1168 //set internal state anyway - as it was done
1169 dh.deviceReason = "tech-profile-config-download-success"
1170 }
1171 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001172 default:
1173 {
1174 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
1175 }
1176 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001177}
1178
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001179func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001180 // parameters are IntfId, OnuId, uniId
1181 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1182 uint32(a_uniId))
1183 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001184 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1185 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001186 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001187 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001188 if pUniPort == nil {
1189 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1190 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001191 //store UniPort with the System-PortNumber key
1192 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001193 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001194 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1195 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1196 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001197 }
1198 }
1199}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001200
mpagenko3af1f032020-06-10 08:53:41 +00001201// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1202func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001203 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1204 // but towards core only the first port active state is signalled
1205 // with following remark:
1206 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1207 // # load on the core
1208
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001209 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001210
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001211 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001212 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001213 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1214 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1215 uniPort.SetOperState(vc.OperStatus_ACTIVE)
1216 //maybe also use getter functions on uniPort - perhaps later ...
mpagenko3af1f032020-06-10 08:53:41 +00001217 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1218 }
1219 }
1220}
1221
1222// Disable UniPortState and update core port state accordingly
1223func (dh *DeviceHandler) disableUniPortStateUpdate() {
1224 // compare enableUniPortStateUpdate() above
1225 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1226 for uniNo, uniPort := range dh.uniEntityMap {
1227 // only if this port is validated for operState transfer
1228 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1229 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1230 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1231 //maybe also use getter functions on uniPort - perhaps later ...
1232 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001233 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001234 }
1235}
1236
1237// ONU_Active/Inactive announcement on system KAFKA bus
1238// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1239func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1240 var de voltha.DeviceEvent
1241 eventContext := make(map[string]string)
1242 //Populating event context
1243 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1244 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1245 if err != nil || parentDevice == nil {
1246 logger.Errorw("Failed to fetch parent device for OnuEvent",
1247 log.Fields{"parentId": dh.parentId, "err": err})
1248 }
1249 oltSerialNumber := parentDevice.SerialNumber
1250
1251 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1252 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1253 eventContext["serial-number"] = dh.device.SerialNumber
1254 eventContext["olt_serial_number"] = oltSerialNumber
1255 eventContext["device_id"] = a_deviceID
1256 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1257 logger.Debugw("prepare ONU_ACTIVATED event",
1258 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1259
1260 /* Populating device event body */
1261 de.Context = eventContext
1262 de.ResourceId = a_deviceID
1263 if a_OperState == voltha.OperStatus_ACTIVE {
1264 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1265 de.Description = fmt.Sprintf("%s Event - %s - %s",
1266 cEventObjectType, cOnuActivatedEvent, "Raised")
1267 } else {
1268 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1269 de.Description = fmt.Sprintf("%s Event - %s - %s",
1270 cEventObjectType, cOnuActivatedEvent, "Cleared")
1271 }
1272 /* Send event to KAFKA */
1273 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1274 logger.Warnw("could not send ONU_ACTIVATED event",
1275 log.Fields{"DeviceId": a_deviceID, "error": err})
1276 }
1277 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1278 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1279}
1280
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001281// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1282func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1283 chLSFsm := make(chan Message, 2048)
1284 var sFsmName string
1285 if aAdminState == true {
1286 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1287 sFsmName = "LockStateFSM"
1288 } else {
1289 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1290 sFsmName = "UnLockStateFSM"
1291 }
mpagenko3af1f032020-06-10 08:53:41 +00001292
1293 pDevEntry := dh.GetOnuDeviceEntry(true)
1294 if pDevEntry == nil {
1295 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1296 return
1297 }
1298 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001299 sFsmName, dh.deviceID, chLSFsm)
1300 if pLSFsm != nil {
1301 if aAdminState == true {
1302 dh.pLockStateFsm = pLSFsm
1303 } else {
1304 dh.pUnlockStateFsm = pLSFsm
1305 }
1306 dh.runUniLockFsm(aAdminState)
1307 } else {
1308 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1309 }
1310}
1311
1312// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1313func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1314 /* Uni Port lock/unlock procedure -
1315 ***** should run via 'adminDone' state and generate the argument requested event *****
1316 */
1317 var pLSStatemachine *fsm.FSM
1318 if aAdminState == true {
1319 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1320 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1321 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001322 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1323 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001324 }
1325 } else {
1326 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1327 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1328 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001329 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1330 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001331 }
1332 }
1333 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001334 if pLSStatemachine.Is(uniStDisabled) {
1335 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001336 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1337 // maybe try a FSM reset and then again ... - TODO!!!
1338 } else {
1339 /***** LockStateFSM started */
1340 logger.Debugw("LockStateFSM started", log.Fields{
1341 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1342 }
1343 } else {
1344 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1345 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1346 // maybe try a FSM reset and then again ... - TODO!!!
1347 }
1348 } else {
1349 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1350 // maybe try a FSM reset and then again ... - TODO!!!
1351 }
1352}
1353
mpagenkoaf801632020-07-03 10:00:42 +00001354//SetBackend provides a DB backend for the specified path on the existing KV client
1355func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1356 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1357 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
1358 "BasePathKvStore": aBasePathKvStore, "deviceId": dh.deviceID})
1359 kvbackend := &db.Backend{
1360 Client: dh.pOpenOnuAc.kvClient,
1361 StoreType: dh.pOpenOnuAc.KVStoreType,
1362 /* address config update acc. to [VOL-2736] */
1363 Address: addr,
1364 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1365 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001366
mpagenkoaf801632020-07-03 10:00:42 +00001367 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001368}