blob: 1aca121f560564d02fb270ec7c0c5b6f7e241f5b [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"
26 "strings"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000027 "sync"
28 "time"
29
30 "github.com/gogo/protobuf/proto"
31 "github.com/golang/protobuf/ptypes"
32 "github.com/looplab/fsm"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +000033 me "github.com/opencord/omci-lib-go/generated"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000034 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
35 "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"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000038 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000039 oop "github.com/opencord/voltha-protos/v3/go/openolt"
40 "github.com/opencord/voltha-protos/v3/go/voltha"
41)
42
43/*
44// Constants for number of retries and for timeout
45const (
46 MaxRetry = 10
47 MaxTimeOutInMs = 500
48)
49*/
50
Holger Hildebrandt24d51952020-05-04 14:03:42 +000051//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
52const (
53 pon = voltha.EventSubCategory_PON
54 olt = voltha.EventSubCategory_OLT
55 ont = voltha.EventSubCategory_ONT
56 onu = voltha.EventSubCategory_ONU
57 nni = voltha.EventSubCategory_NNI
58 service = voltha.EventCategory_SERVICE
59 security = voltha.EventCategory_SECURITY
60 equipment = voltha.EventCategory_EQUIPMENT
61 processing = voltha.EventCategory_PROCESSING
62 environment = voltha.EventCategory_ENVIRONMENT
63 communication = voltha.EventCategory_COMMUNICATION
64)
65
66const (
67 cEventObjectType = "ONU"
68)
69const (
70 cOnuActivatedEvent = "ONU_ACTIVATED"
71)
72
Holger Hildebrandtc54939a2020-06-17 08:14:27 +000073type resourceEntry int
74
75const (
76 cResourceGemPort resourceEntry = 1
77 cResourceTcont resourceEntry = 2
78)
79
80type OnuSerialNumber struct {
81 VendorId []byte
82 VendorSpecific []byte
83}
84
85type onuPersistentData struct {
86 persOnuID uint32
87 persIntfID uint32
88 persSnr OnuSerialNumber
89 persAdminState string
90 persOperState string
91 persUniTpPath map[uint32]string
92}
93
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000094//DeviceHandler will interact with the ONU ? device.
95type DeviceHandler struct {
96 deviceID string
97 DeviceType string
98 adminState string
99 device *voltha.Device
100 logicalDeviceID string
101 ProxyAddressID string
102 ProxyAddressType string
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000103 parentId string
104 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000105
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000106 coreProxy adapterif.CoreProxy
107 AdapterProxy adapterif.AdapterProxy
108 EventProxy adapterif.EventProxy
109
110 tpProcMutex sync.RWMutex
111 sOnuPersistentData onuPersistentData
112
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000113 pOpenOnuAc *OpenONUAC
114 pDeviceStateFsm *fsm.FSM
115 pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +0000116 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000117 pOnuOmciDevice *OnuDeviceEntry
118 exitChannel chan int
119 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000120 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +0000121 deviceReason string
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000122 pLockStateFsm *LockStateFsm
123 pUnlockStateFsm *LockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000124
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000125 //flowMgr *OpenOltFlowMgr
126 //eventMgr *OpenOltEventMgr
127 //resourceMgr *rsrcMgr.OpenOltResourceMgr
128
129 //discOnus sync.Map
130 //onus sync.Map
131 //portStats *OpenOltStatisticsMgr
132 //metrics *pmmetrics.PmMetrics
133 stopCollector chan bool
134 stopHeartbeatCheck chan bool
135 activePorts sync.Map
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000136 uniEntityMap map[uint32]*OnuUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000137}
138
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000139//NewDeviceHandler creates a new device handler
140func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *DeviceHandler {
141 var dh DeviceHandler
142 dh.coreProxy = cp
143 dh.AdapterProxy = ap
144 dh.EventProxy = ep
145 cloned := (proto.Clone(device)).(*voltha.Device)
146 dh.deviceID = cloned.Id
147 dh.DeviceType = cloned.Type
148 dh.adminState = "up"
149 dh.device = cloned
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000150 dh.tpProcMutex = sync.RWMutex{}
151 dh.sOnuPersistentData.persUniTpPath = make(map[uint32]string)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000152 dh.pOpenOnuAc = adapter
153 dh.exitChannel = make(chan int, 1)
154 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000155 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000156 dh.stopCollector = make(chan bool, 2)
157 dh.stopHeartbeatCheck = make(chan bool, 2)
158 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
159 dh.activePorts = sync.Map{}
160 //TODO initialize the support classes.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000161 dh.uniEntityMap = make(map[uint32]*OnuUniPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000162
163 // Device related state machine
164 dh.pDeviceStateFsm = fsm.NewFSM(
165 "null",
166 fsm.Events{
167 {Name: "DeviceInit", Src: []string{"null", "down"}, Dst: "init"},
168 {Name: "GrpcConnected", Src: []string{"init"}, Dst: "connected"},
169 {Name: "GrpcDisconnected", Src: []string{"connected", "down"}, Dst: "init"},
170 {Name: "DeviceUpInd", Src: []string{"connected", "down"}, Dst: "up"},
171 {Name: "DeviceDownInd", Src: []string{"up"}, Dst: "down"},
172 },
173 fsm.Callbacks{
174 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
175 "before_DeviceInit": func(e *fsm.Event) { dh.doStateInit(e) },
176 "after_DeviceInit": func(e *fsm.Event) { dh.postInit(e) },
177 "before_GrpcConnected": func(e *fsm.Event) { dh.doStateConnected(e) },
178 "before_GrpcDisconnected": func(e *fsm.Event) { dh.doStateInit(e) },
179 "after_GrpcDisconnected": func(e *fsm.Event) { dh.postInit(e) },
180 "before_DeviceUpInd": func(e *fsm.Event) { dh.doStateUp(e) },
181 "before_DeviceDownInd": func(e *fsm.Event) { dh.doStateDown(e) },
182 },
183 )
184 return &dh
185}
186
187// start save the device to the data model
188func (dh *DeviceHandler) Start(ctx context.Context) {
189 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "deviceId": dh.deviceID})
190 // Add the initial device to the local model
191 logger.Debug("device-handler-started")
192}
193
194// stop stops the device dh. Not much to do for now
195func (dh *DeviceHandler) stop(ctx context.Context) {
196 logger.Debug("stopping-device-handler")
197 dh.exitChannel <- 1
198}
199
200// ##########################################################################################
201// DeviceHandler methods that implement the adapters interface requests ##### begin #########
202
203//AdoptDevice adopts the OLT device
204func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
205 logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
206
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000207 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000208 if dh.pDeviceStateFsm.Is("null") {
209 if err := dh.pDeviceStateFsm.Event("DeviceInit"); err != nil {
210 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
211 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000212 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000213 } else {
214 logger.Debug("AdoptDevice: Agent/device init already done")
215 }
216
217 /*
218 // Now, set the initial PM configuration for that device
219 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
220 logger.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
221 }
222
223 go startCollector(dh)
224 go startHeartbeatCheck(dh)
225 */
226}
227
228//ProcessInterAdapterMessage sends the proxied messages to the target device
229// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
230// is meant, and then send the unmarshalled omci message to this onu
231func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
232 msgID := msg.Header.Id
233 msgType := msg.Header.Type
234 fromTopic := msg.Header.FromTopic
235 toTopic := msg.Header.ToTopic
236 toDeviceID := msg.Header.ToDeviceId
237 proxyDeviceID := msg.Header.ProxyDeviceId
238 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
239 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
240
241 switch msgType {
242 case ic.InterAdapterMessageType_OMCI_REQUEST:
243 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000244 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000245 omciMsg := &ic.InterAdapterOmciMessage{}
246 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000247 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
248 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000249 return err
250 }
251
252 //assuming omci message content is hex coded!
253 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000254 logger.Debugw("inter-adapter-recv-omci", log.Fields{
255 "deviceID": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000256 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000257 pDevEntry := dh.GetOnuDeviceEntry(true)
258 if pDevEntry != nil {
259 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
260 } else {
261 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
262 return errors.New("No valid OnuDevice")
263 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000264 }
265 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
266 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000267 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000268 onu_indication := &oop.OnuIndication{}
269 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000270 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
271 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000272 return err
273 }
274
275 onu_operstate := onu_indication.GetOperState()
276 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
277 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
278 "SNR": onu_indication.GetSerialNumber()})
279
mpagenko3af1f032020-06-10 08:53:41 +0000280 //interface related functions might be error checked ....
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000281 if onu_operstate == "up" {
282 dh.create_interface(onu_indication)
283 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
mpagenko3af1f032020-06-10 08:53:41 +0000284 dh.updateInterface(onu_indication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000285 } else {
286 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
287 return errors.New("InvalidOperState")
288 }
289 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000290 // TODO: temporarily commented out - see https://gerrit.opencord.org/#/c/19330/
291 // case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
292 // {
293 // msgBody := msg.GetBody()
294 // techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
295 // if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
296 // logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
297 // "deviceID": dh.deviceID, "error": err})
298 // return err
299 // }
300 // // we have to lock access to TechProfile processing based on different messageType calls or
301 // // even to fast subsequent calls of the same messageType
302 // dh.tpProcMutex.Lock()
303 // // lock hangs as long as below decoupled or other related TechProfile processing is active
304 // if bTpModify := dh.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify == true {
305 // // if there has been some change for some uni TechProfilePath
306 // //in order to allow concurrent calls to other dh instances we do not wait for execution here
307 // //but doing so we can not indicate problems to the caller (who does what with that then?)
308 // //by now we just assume straightforward successful execution
309 // //TODO!!! Generally: In this scheme it would be good to have some means to indicate
310 // // possible problems to the caller later autonomously
311
312 // // some code to coordinate TP 'run to completion'
313 // // attention: completion and wg.Add is assumed to be doen in both routines,
314 // // no timeout control so far (needed)
315 // var wg sync.WaitGroup
316 // wg.Add(2) // for the 2 go routines to finish
317 // go dh.configureUniTp(techProfMsg.UniId, techProfMsg.Path, &wg)
318 // go dh.updateOnuTpPathKvStore(&wg)
319 // //the wait.. function is responsible for tpProcMutex.Unlock()
320 // go dh.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
321 // } else {
322 // dh.tpProcMutex.Unlock()
323 // }
324 // }
325 // case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
326 // {
327 // msgBody := msg.GetBody()
328 // delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
329 // if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
330 // logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
331 // "deviceID": dh.deviceID, "error": err})
332 // return err
333 // }
334
335 // //compare TECH_PROFILE_DOWNLOAD_REQUEST
336 // dh.tpProcMutex.Lock()
337 // var wg sync.WaitGroup
338 // wg.Add(1) // for the 1 go routine to finish
339 // go dh.deleteTpRessource(delGemPortMsg.UniId, delGemPortMsg.TpPath,
340 // cResourceGemPort, delGemPortMsg.GemPortId, &wg)
341 // //the wait.. function is responsible for tpProcMutex.Unlock()
342 // go dh.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
343 // }
344 // case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
345 // {
346 // msgBody := msg.GetBody()
347 // delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
348 // if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
349 // logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
350 // "deviceID": dh.deviceID, "error": err})
351 // return err
352 // }
353
354 // //compare TECH_PROFILE_DOWNLOAD_REQUEST
355 // dh.tpProcMutex.Lock()
356 // if bTpModify := dh.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify == true {
357 // var wg sync.WaitGroup
358 // wg.Add(2) // for the 1 go routine to finish
359 // go dh.deleteTpRessource(delTcontMsg.UniId, delTcontMsg.TpPath,
360 // cResourceTcont, delTcontMsg.AllocId, &wg)
361 // // Removal of the tcont/alloc id mapping represents the removal of the tech profile
362 // go dh.updateOnuTpPathKvStore(&wg)
363 // //the wait.. function is responsible for tpProcMutex.Unlock()
364 // go dh.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
365 // } else {
366 // dh.tpProcMutex.Unlock()
367 // }
368 // }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000369 default:
370 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000371 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
372 "deviceID": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000373 return errors.New("unimplemented")
374 }
375 }
376
377 /* form py code:
378 elif request.header.type == InterAdapterMessageType.TECH_PROFILE_DOWNLOAD_REQUEST:
379 tech_msg = InterAdapterTechProfileDownloadMessage()
380 request.body.Unpack(tech_msg)
381 self.logger.debug('inter-adapter-recv-tech-profile', tech_msg=tech_msg)
382
383 self.load_and_configure_tech_profile(tech_msg.uni_id, tech_msg.path)
384
385 elif request.header.type == InterAdapterMessageType.DELETE_GEM_PORT_REQUEST:
386 del_gem_msg = InterAdapterDeleteGemPortMessage()
387 request.body.Unpack(del_gem_msg)
388 self.logger.debug('inter-adapter-recv-del-gem', gem_del_msg=del_gem_msg)
389
390 self.delete_tech_profile(uni_id=del_gem_msg.uni_id,
391 gem_port_id=del_gem_msg.gem_port_id,
392 tp_path=del_gem_msg.tp_path)
393
394 elif request.header.type == InterAdapterMessageType.DELETE_TCONT_REQUEST:
395 del_tcont_msg = InterAdapterDeleteTcontMessage()
396 request.body.Unpack(del_tcont_msg)
397 self.logger.debug('inter-adapter-recv-del-tcont', del_tcont_msg=del_tcont_msg)
398
399 self.delete_tech_profile(uni_id=del_tcont_msg.uni_id,
400 alloc_id=del_tcont_msg.alloc_id,
401 tp_path=del_tcont_msg.tp_path)
402 else:
403 self.logger.error("inter-adapter-unhandled-type", request=request)
404 */
405 return nil
406}
407
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000408//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000409// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
410// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300411func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000412 logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
413
mpagenko3af1f032020-06-10 08:53:41 +0000414 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
415 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
416 if dh.deviceReason != "omci-admin-lock" {
417 // disable UNI ports/ONU
418 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
419 // here the result of the processing is not checked (trusted in background) *****
420 if dh.pLockStateFsm == nil {
421 dh.createUniLockFsm(true, UniAdminStateDone)
422 } else { //LockStateFSM already init
423 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
424 dh.runUniLockFsm(true)
425 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300426
mpagenko3af1f032020-06-10 08:53:41 +0000427 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
428 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
429 }
430 dh.deviceReason = "omci-admin-lock"
431 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
432 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
433 voltha.OperStatus_UNKNOWN); err != nil {
434 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
435 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300436 }
437}
438
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000439//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000440// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
441// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300442func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000443 logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000444
445 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300446 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
447 voltha.OperStatus_ACTIVE); err != nil {
448 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
449 }
450
mpagenko3af1f032020-06-10 08:53:41 +0000451 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000452 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
ozgecanetsiafce57b12020-05-25 14:39:35 +0300453 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
454 }
mpagenko3af1f032020-06-10 08:53:41 +0000455 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000456
457 // enable ONU/UNI ports
458 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
459 // here the result of the processing is not checked (trusted in background) *****
460 if dh.pUnlockStateFsm == nil {
461 dh.createUniLockFsm(false, UniAdminStateDone)
462 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000463 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000464 dh.runUniLockFsm(false)
465 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300466}
467
mpagenko3af1f032020-06-10 08:53:41 +0000468//GetOfpPortInfo returns the Voltha PortCapabilty with the logical port
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000469func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
470 portNo int64) (*ic.PortCapability, error) {
471 logger.Debugw("GetOfpPortInfo start", log.Fields{"deviceID": device.Id, "portNo": portNo})
472
473 //function body as per OLTAdapter handler code
474 // adapted with values from py dapter code
475 if pUniPort, exist := dh.uniEntityMap[uint32(portNo)]; exist {
476 var macOctets [6]uint8
477 macOctets[5] = 0x08
478 macOctets[4] = uint8(dh.ponPortNumber >> 8)
479 macOctets[3] = uint8(dh.ponPortNumber)
480 macOctets[2] = uint8(portNo >> 16)
481 macOctets[1] = uint8(portNo >> 8)
482 macOctets[0] = uint8(portNo)
483 hwAddr := genMacFromOctets(macOctets)
484 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
485 name := device.SerialNumber + "-" + strconv.FormatUint(uint64(pUniPort.macBpNo), 10)
486 ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
487 if pUniPort.operState == vc.OperStatus_ACTIVE {
488 ofUniPortState = of.OfpPortState_OFPPS_LIVE
489 }
490 logger.Debugw("setting LogicalPort", log.Fields{"with-name": name,
491 "withUniPort": pUniPort.name, "withMacBase": hwAddr, "OperState": ofUniPortState})
492
493 return &ic.PortCapability{
494 Port: &voltha.LogicalPort{
495 OfpPort: &of.OfpPort{
496 Name: name,
497 //HwAddr: macAddressToUint32Array(dh.device.MacAddress),
498 HwAddr: macAddressToUint32Array(hwAddr),
499 Config: 0,
500 State: uint32(ofUniPortState),
501 Curr: capacity,
502 Advertised: capacity,
503 Peer: capacity,
504 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
505 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
506 },
507 DeviceId: device.Id,
508 DevicePortNo: uint32(portNo),
509 },
510 }, nil
511 }
512 logger.Warnw("No UniPort found - abort", log.Fields{"for PortNo": uint32(portNo)})
513 return nil, errors.New("UniPort not found")
514}
515
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000516// DeviceHandler methods that implement the adapters interface requests## end #########
517// #####################################################################################
518
519// ################ to be updated acc. needs of ONU Device ########################
520// DeviceHandler StateMachine related state transition methods ##### begin #########
521
522func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
523 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})
524}
525
526// doStateInit provides the device update to the core
527func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
528
529 logger.Debug("doStateInit-started")
530 var err error
531
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000532 // populate what we know. rest comes later after mib sync
533 dh.device.Root = false
534 dh.device.Vendor = "OpenONU"
535 dh.device.Model = "go"
536 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000537 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000538
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000539 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000540 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
541
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000542 dh.parentId = dh.device.ParentId
543 dh.ponPortNumber = dh.device.ParentPortNo
544
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000545 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
546 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
547 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
548 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
549 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000550 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000551
552 /*
553 self._pon = PonPort.create(self, self._pon_port_number)
554 self._pon.add_peer(self.parent_id, self._pon_port_number)
555 self.logger.debug('adding-pon-port-to-agent',
556 type=self._pon.get_port().type,
557 admin_state=self._pon.get_port().admin_state,
558 oper_status=self._pon.get_port().oper_status,
559 )
560 */
561 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000562 var ponPortNo uint32 = 1
563 if dh.ponPortNumber != 0 {
564 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000565 }
566
567 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000568 PortNo: ponPortNo,
569 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000570 Type: voltha.Port_PON_ONU,
571 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000572 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
573 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000574 }
575 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
576 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
577 e.Cancel(err)
578 return
579 }
580 logger.Debug("doStateInit-done")
581}
582
583// postInit setups the DeviceEntry for the conerned device
584func (dh *DeviceHandler) postInit(e *fsm.Event) {
585
586 logger.Debug("postInit-started")
587 var err error
588 /*
589 dh.Client = oop.NewOpenoltClient(dh.clientCon)
590 dh.pTransitionMap.Handle(ctx, GrpcConnected)
591 return nil
592 */
mpagenko3af1f032020-06-10 08:53:41 +0000593 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
594 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000595 e.Cancel(err)
596 return
597 }
598
599 /*
600 ############################################################################
601 # Setup Alarm handler
602 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
603 device.serial_number)
604 ############################################################################
605 # Setup PM configuration for this device
606 # Pass in ONU specific options
607 kwargs = {
608 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
609 'heartbeat': self.heartbeat,
610 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
611 }
612 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
613 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
614 self.logical_device_id, device.serial_number,
615 grouped=True, freq_override=False, **kwargs)
616 pm_config = self._pm_metrics.make_proto()
617 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
618 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
619 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
620
621 # Note, ONU ID and UNI intf set in add_uni_port method
622 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
623 ani_ports=[self._pon])
624
625 # Code to Run OMCI Test Action
626 kwargs_omci_test_action = {
627 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
628 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
629 }
630 serial_number = device.serial_number
631 self._test_request = OmciTestRequest(self.core_proxy,
632 self.omci_agent, self.device_id,
633 AniG, serial_number,
634 self.logical_device_id,
635 exclusive=False,
636 **kwargs_omci_test_action)
637
638 self.enabled = True
639 else:
640 self.logger.info('onu-already-activated')
641 */
642 logger.Debug("postInit-done")
643}
644
645// doStateConnected get the device info and update to voltha core
646// for comparison of the original method (not that easy to uncomment): compare here:
647// voltha-openolt-adapter/adaptercore/device_handler.go
648// -> this one obviously initiates all communication interfaces of the device ...?
649func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
650
651 logger.Debug("doStateConnected-started")
652 var err error
653 err = errors.New("Device FSM: function not implemented yet!")
654 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000655 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700656 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000657}
658
659// doStateUp handle the onu up indication and update to voltha core
660func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
661
662 logger.Debug("doStateUp-started")
663 var err error
664 err = errors.New("Device FSM: function not implemented yet!")
665 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000666 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700667 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000668
669 /*
670 // Synchronous call to update device state - this method is run in its own go routine
671 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
672 voltha.OperStatus_ACTIVE); err != nil {
673 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
674 return err
675 }
676 return nil
677 */
678}
679
680// doStateDown handle the onu down indication
681func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
682
683 logger.Debug("doStateDown-started")
684 var err error
685
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000686 device := dh.device
687 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000688 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000689 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000690 e.Cancel(err)
691 return
692 }
693
694 cloned := proto.Clone(device).(*voltha.Device)
695 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
696 /*
697 // Update the all ports state on that device to disable
698 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
699 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
700 return er
701 }
702
703 //Update the device oper state and connection status
704 cloned.OperStatus = voltha.OperStatus_UNKNOWN
705 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
706 dh.device = cloned
707
708 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
709 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
710 return er
711 }
712
713 //get the child device for the parent device
714 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
715 if err != nil {
716 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
717 return err
718 }
719 for _, onuDevice := range onuDevices.Items {
720
721 // Update onu state as down in onu adapter
722 onuInd := oop.OnuIndication{}
723 onuInd.OperState = "down"
724 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
725 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
726 if er != nil {
727 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
728 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
729 //Do not return here and continue to process other ONUs
730 }
731 }
732 // * Discovered ONUs entries need to be cleared , since after OLT
733 // is up, it starts sending discovery indications again* /
734 dh.discOnus = sync.Map{}
735 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
736 return nil
737 */
738 err = errors.New("Device FSM: function not implemented yet!")
739 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000740 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700741 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000742}
743
744// DeviceHandler StateMachine related state transition methods ##### end #########
745// #################################################################################
746
747// ###################################################
748// DeviceHandler utility methods ##### begin #########
749
mpagenko3af1f032020-06-10 08:53:41 +0000750//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
751func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
752 dh.lockDevice.RLock()
753 pOnuDeviceEntry := dh.pOnuOmciDevice
754 if aWait && pOnuDeviceEntry == nil {
755 //keep the read sema short to allow for subsequent write
756 dh.lockDevice.RUnlock()
757 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"deviceID": dh.deviceID})
758 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
759 // so it might be needed to wait here for that event with some timeout
760 select {
761 case <-time.After(60 * time.Second): //timer may be discussed ...
762 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"deviceID": dh.deviceID})
763 return nil
764 case <-dh.deviceEntrySet:
765 logger.Debugw("devicEntry ready now - continue", log.Fields{"deviceID": dh.deviceID})
766 // if written now, we can return the written value without sema
767 return dh.pOnuOmciDevice
768 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000769 }
mpagenko3af1f032020-06-10 08:53:41 +0000770 dh.lockDevice.RUnlock()
771 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000772}
773
mpagenko3af1f032020-06-10 08:53:41 +0000774//SetOnuDeviceEntry sets the ONU device entry within the handler
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000775func (dh *DeviceHandler) SetOnuDeviceEntry(pDeviceEntry *OnuDeviceEntry) error {
776 dh.lockDevice.Lock()
777 defer dh.lockDevice.Unlock()
778 dh.pOnuOmciDevice = pDeviceEntry
779 return nil
780}
781
mpagenko3af1f032020-06-10 08:53:41 +0000782//AddOnuDeviceEntry creates a new ONU device or returns the existing
783func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000784 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
785
mpagenko3af1f032020-06-10 08:53:41 +0000786 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000787 if deviceEntry == nil {
788 /* costum_me_map in python code seems always to be None,
789 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
790 /* also no 'clock' argument - usage open ...*/
791 /* and no alarm_db yet (oo.alarm_db) */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000792 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost, dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
793 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000794 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
795 //error treatment possible //TODO!!!
796 dh.SetOnuDeviceEntry(deviceEntry)
mpagenko3af1f032020-06-10 08:53:41 +0000797 // fire deviceEntry ready event to spread to possibly waiting processing
798 dh.deviceEntrySet <- true
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000799 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
800 } else {
801 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
802 }
803 // might be updated with some error handling !!!
804 return nil
805}
806
807// doStateInit provides the device update to the core
808func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000809 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
810 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
811
812 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000813
mpagenko3af1f032020-06-10 08:53:41 +0000814 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
815 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000816 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
817 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000818 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
819 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
820 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
821 // but I would not know why, and the go code anyway dows not work with the device directly anymore in the OnuDeviceEntry
822 // so let's just try to keep it simple ...
823 /*
824 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
825 if err != nil || device == nil {
826 //TODO: needs to handle error scenarios
827 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
828 return errors.New("Voltha Device not found")
829 }
830 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000831
mpagenko3af1f032020-06-10 08:53:41 +0000832 pDevEntry := dh.GetOnuDeviceEntry(true)
833 if pDevEntry != nil {
834 pDevEntry.Start(context.TODO())
835 } else {
836 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
837 return errors.New("No valid OnuDevice")
838 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000839 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
840 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
841 }
mpagenko3af1f032020-06-10 08:53:41 +0000842 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000843
844 /* this might be a good time for Omci Verify message? */
845 verifyExec := make(chan bool)
846 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000847 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000848 true, true) //eclusive and allowFailure (anyway not yet checked)
849 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
850
851 /* give the handler some time here to wait for the OMCi verification result
852 after Timeout start and try MibUpload FSM anyway
853 (to prevent stopping on just not supported OMCI verification from ONU) */
854 select {
855 case <-time.After(2 * time.Second):
856 logger.Warn("omci start-verification timed out (continue normal)")
857 case testresult := <-verifyExec:
858 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
859 }
860
861 /* In py code it looks earlier (on activate ..)
862 # Code to Run OMCI Test Action
863 kwargs_omci_test_action = {
864 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
865 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
866 }
867 serial_number = device.serial_number
868 self._test_request = OmciTestRequest(self.core_proxy,
869 self.omci_agent, self.device_id,
870 AniG, serial_number,
871 self.logical_device_id,
872 exclusive=False,
873 **kwargs_omci_test_action)
874 ...
875 # Start test requests after a brief pause
876 if not self._test_request_started:
877 self._test_request_started = True
878 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
879 reactor.callLater(tststart, self._test_request.start_collector)
880
881 */
882 /* which is then: in omci_test_request.py : */
883 /*
884 def start_collector(self, callback=None):
885 """
886 Start the collection loop for an adapter if the frequency > 0
887
888 :param callback: (callable) Function to call to collect PM data
889 """
890 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
891 if callback is None:
892 callback = self.perform_test_omci
893
894 if self.lc is None:
895 self.lc = LoopingCall(callback)
896
897 if self.default_freq > 0:
898 self.lc.start(interval=self.default_freq / 10)
899
900 def perform_test_omci(self):
901 """
902 Perform the initial test request
903 """
904 ani_g_entities = self._device.configuration.ani_g_entities
905 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
906 is not None else None
907 self._entity_id = ani_g_entities_ids[0]
908 self.logger.info('perform-test', entity_class=self._entity_class,
909 entity_id=self._entity_id)
910 try:
911 frame = MEFrame(self._entity_class, self._entity_id, []).test()
912 result = yield self._device.omci_cc.send(frame)
913 if not result.fields['omci_message'].fields['success_code']:
914 self.logger.info('Self-Test Submitted Successfully',
915 code=result.fields[
916 'omci_message'].fields['success_code'])
917 else:
918 raise TestFailure('Test Failure: {}'.format(
919 result.fields['omci_message'].fields['success_code']))
920 except TimeoutError as e:
921 self.deferred.errback(failure.Failure(e))
922
923 except Exception as e:
924 self.logger.exception('perform-test-Error', e=e,
925 class_id=self._entity_class,
926 entity_id=self._entity_id)
927 self.deferred.errback(failure.Failure(e))
928
929 */
930
931 // PM related heartbeat??? !!!TODO....
932 //self._heartbeat.enabled = True
933
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000934 //call MibUploadFSM - transition up to state "in_sync"
mpagenko3af1f032020-06-10 08:53:41 +0000935 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000936 if pMibUlFsm != nil {
937 if pMibUlFsm.Is("disabled") {
938 if err := pMibUlFsm.Event("start"); err != nil {
939 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
940 return errors.New("Can't go to state starting")
941 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000942 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000943 //Determine ONU status and start/re-start MIB Synchronization tasks
944 //Determine if this ONU has ever synchronized
945 if true { //TODO: insert valid check
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000946 if err := pMibUlFsm.Event("reset_mib"); err != nil {
947 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
948 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000949 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000950 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000951 pMibUlFsm.Event("examine_mds")
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000952 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000953 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000954 // callbacks to be handled:
955 // Event("success")
956 // Event("timeout")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000957 // Event("mismatch")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000958 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000959 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000960 } else {
961 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
962 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000963 }
964 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000965 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000966 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000967 }
968 return nil
969}
970
mpagenko3af1f032020-06-10 08:53:41 +0000971func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
972 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
973 if dh.deviceReason != "stopping-openomci" {
974 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"deviceID": dh.deviceID})
975 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
976 pDevEntry := dh.GetOnuDeviceEntry(false)
977 if pDevEntry == nil {
978 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
979 return errors.New("No valid OnuDevice")
980 }
981
982 switch dh.deviceReason {
983 case "starting-openomci":
984 { //MIBSync FSM may run
985 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
986 if pMibUlFsm != nil {
987 pMibUlFsm.Event("stop") //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
988 }
989 }
990 case "discovery-mibsync-complete":
991 { //MibDownload may run
992 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
993 if pMibDlFsm != nil {
994 pMibDlFsm.Event("reset")
995 }
996 }
997 default:
998 { //port lock/unlock FSM's may be active
999 if dh.pUnlockStateFsm != nil {
1000 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
1001 }
1002 if dh.pLockStateFsm != nil {
1003 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
1004 }
1005 }
1006 //TODO!!! care about PM/Alarm processing once started
1007 }
1008 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
1009 // (mainly the still seperate 'Event states')
1010 // so it is questionable, how this is resolved after some possible re-enable
1011 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1012
1013 //stop/remove(?) the device entry
1014 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
1015
1016 //TODO!!! remove existing traffic profiles
1017 /* from py code, if TP's exist, remove them - not yet implemented
1018 self._tp = dict()
1019 # Let TP download happen again
1020 for uni_id in self._tp_service_specific_task:
1021 self._tp_service_specific_task[uni_id].clear()
1022 for uni_id in self._tech_profile_download_done:
1023 self._tech_profile_download_done[uni_id].clear()
1024 */
1025
1026 dh.disableUniPortStateUpdate()
1027
1028 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
1029 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
1030 log.Fields{"deviceID": dh.deviceID, "error": err})
1031 // abort: system behavior is just unstable ...
1032 return err
1033 }
1034 dh.deviceReason = "stopping-openomci"
1035
1036 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1037 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
1038 logger.Errorw("error-updating-device-state unreachable-discovered",
1039 log.Fields{"deviceID": dh.deviceID, "error": err})
1040 // abort: system behavior is just unstable ...
1041 return err
1042 }
1043 } else {
1044 logger.Debugw("updateInterface - device already stopped", log.Fields{"deviceID": dh.deviceID})
1045 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001046 return nil
1047}
1048
mpagenko3af1f032020-06-10 08:53:41 +00001049//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001050func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
1051 switch dev_Event {
1052 case MibDatabaseSync:
1053 {
1054 logger.Infow("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
1055 //initiate DevStateUpdate
1056 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1057 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1058 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001059 }
mpagenko3af1f032020-06-10 08:53:41 +00001060 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001061
mpagenko3af1f032020-06-10 08:53:41 +00001062 pDevEntry := dh.GetOnuDeviceEntry(false)
1063 unigMap, ok := pDevEntry.pOnuDB.meDb[me.UniGClassID]
1064 unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(unigMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001065 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
1066 if ok {
1067 for _, mgmtEntityId := range unigInstKeys {
1068 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1069 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
1070 dh.addUniPort(mgmtEntityId, i, UniPPTP)
1071 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001072 }
1073 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001074 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001075 }
mpagenko3af1f032020-06-10 08:53:41 +00001076 veipMap, ok := pDevEntry.pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
1077 veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(veipMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001078 if ok {
1079 for _, mgmtEntityId := range veipInstKeys {
1080 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1081 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
1082 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1083 i++
1084 }
1085 } else {
1086 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
1087 }
1088 if i == 0 {
1089 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
1090 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001091
mpagenko3af1f032020-06-10 08:53:41 +00001092 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1093 * left the code here as comment in case such processing should prove needed unexpectedly
1094 // Init Uni Ports to Admin locked state
1095 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1096 // *** should generate UniLockStateDone event *****
1097 if dh.pLockStateFsm == nil {
1098 dh.createUniLockFsm(true, UniLockStateDone)
1099 } else { //LockStateFSM already init
1100 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1101 dh.runUniLockFsm(true)
1102 }
1103 }
1104 case UniLockStateDone:
1105 {
1106 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
1107 * lockState processing commented out
1108 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001109 /* Mib download procedure -
1110 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1111 */
mpagenko3af1f032020-06-10 08:53:41 +00001112 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001113 if pMibDlFsm != nil {
1114 if pMibDlFsm.Is("disabled") {
1115 if err := pMibDlFsm.Event("start"); err != nil {
1116 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1117 // maybe try a FSM reset and then again ... - TODO!!!
1118 } else {
1119 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1120 // maybe use more specific states here for the specific download steps ...
1121 if err := pMibDlFsm.Event("create_gal"); err != nil {
1122 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1123 } else {
1124 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1125 //Begin MIB data download (running autonomously)
1126 }
1127 }
1128 } else {
1129 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1130 // maybe try a FSM reset and then again ... - TODO!!!
1131 }
1132 /***** Mib download started */
1133 } else {
1134 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1135 }
1136 }
1137 case MibDownloadDone:
1138 {
1139 logger.Infow("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
1140 //initiate DevStateUpdate
1141 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1142 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1143 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
1144 }
mpagenko3af1f032020-06-10 08:53:41 +00001145
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001146 logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
1147 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1148 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1149 log.Fields{"deviceID": dh.deviceID, "error": err})
1150 }
mpagenko3af1f032020-06-10 08:53:41 +00001151 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001152
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001153 // *** should generate UniUnlockStateDone event *****
1154 if dh.pUnlockStateFsm == nil {
1155 dh.createUniLockFsm(false, UniUnlockStateDone)
1156 } else { //UnlockStateFSM already init
1157 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1158 dh.runUniLockFsm(false)
1159 }
1160 }
1161 case UniUnlockStateDone:
1162 {
mpagenko3af1f032020-06-10 08:53:41 +00001163 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001164
1165 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
1166 raisedTs := time.Now().UnixNano()
1167 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1168 }
1169 default:
1170 {
1171 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
1172 }
1173 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001174}
1175
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001176func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001177 // parameters are IntfId, OnuId, uniId
1178 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1179 uint32(a_uniId))
1180 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001181 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1182 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001183 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001184 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001185 if pUniPort == nil {
1186 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1187 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001188 //store UniPort with the System-PortNumber key
1189 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001190 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001191 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1192 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1193 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001194 }
1195 }
1196}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001197
mpagenko3af1f032020-06-10 08:53:41 +00001198// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1199func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001200 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1201 // but towards core only the first port active state is signalled
1202 // with following remark:
1203 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1204 // # load on the core
1205
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001206 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001207
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001208 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001209 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001210 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1211 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1212 uniPort.SetOperState(vc.OperStatus_ACTIVE)
1213 //maybe also use getter functions on uniPort - perhaps later ...
mpagenko3af1f032020-06-10 08:53:41 +00001214 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1215 }
1216 }
1217}
1218
1219// Disable UniPortState and update core port state accordingly
1220func (dh *DeviceHandler) disableUniPortStateUpdate() {
1221 // compare enableUniPortStateUpdate() above
1222 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1223 for uniNo, uniPort := range dh.uniEntityMap {
1224 // only if this port is validated for operState transfer
1225 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1226 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1227 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1228 //maybe also use getter functions on uniPort - perhaps later ...
1229 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001230 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001231 }
1232}
1233
1234// ONU_Active/Inactive announcement on system KAFKA bus
1235// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1236func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1237 var de voltha.DeviceEvent
1238 eventContext := make(map[string]string)
1239 //Populating event context
1240 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1241 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1242 if err != nil || parentDevice == nil {
1243 logger.Errorw("Failed to fetch parent device for OnuEvent",
1244 log.Fields{"parentId": dh.parentId, "err": err})
1245 }
1246 oltSerialNumber := parentDevice.SerialNumber
1247
1248 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1249 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1250 eventContext["serial-number"] = dh.device.SerialNumber
1251 eventContext["olt_serial_number"] = oltSerialNumber
1252 eventContext["device_id"] = a_deviceID
1253 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1254 logger.Debugw("prepare ONU_ACTIVATED event",
1255 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1256
1257 /* Populating device event body */
1258 de.Context = eventContext
1259 de.ResourceId = a_deviceID
1260 if a_OperState == voltha.OperStatus_ACTIVE {
1261 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1262 de.Description = fmt.Sprintf("%s Event - %s - %s",
1263 cEventObjectType, cOnuActivatedEvent, "Raised")
1264 } else {
1265 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1266 de.Description = fmt.Sprintf("%s Event - %s - %s",
1267 cEventObjectType, cOnuActivatedEvent, "Cleared")
1268 }
1269 /* Send event to KAFKA */
1270 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1271 logger.Warnw("could not send ONU_ACTIVATED event",
1272 log.Fields{"DeviceId": a_deviceID, "error": err})
1273 }
1274 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1275 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1276}
1277
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001278// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1279func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1280 chLSFsm := make(chan Message, 2048)
1281 var sFsmName string
1282 if aAdminState == true {
1283 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1284 sFsmName = "LockStateFSM"
1285 } else {
1286 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1287 sFsmName = "UnLockStateFSM"
1288 }
mpagenko3af1f032020-06-10 08:53:41 +00001289
1290 pDevEntry := dh.GetOnuDeviceEntry(true)
1291 if pDevEntry == nil {
1292 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1293 return
1294 }
1295 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001296 sFsmName, dh.deviceID, chLSFsm)
1297 if pLSFsm != nil {
1298 if aAdminState == true {
1299 dh.pLockStateFsm = pLSFsm
1300 } else {
1301 dh.pUnlockStateFsm = pLSFsm
1302 }
1303 dh.runUniLockFsm(aAdminState)
1304 } else {
1305 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1306 }
1307}
1308
1309// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1310func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1311 /* Uni Port lock/unlock procedure -
1312 ***** should run via 'adminDone' state and generate the argument requested event *****
1313 */
1314 var pLSStatemachine *fsm.FSM
1315 if aAdminState == true {
1316 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1317 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1318 if (dh.pUnlockStateFsm != nil) &&
1319 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1320 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
1321 }
1322 } else {
1323 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1324 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1325 if (dh.pLockStateFsm != nil) &&
1326 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1327 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
1328 }
1329 }
1330 if pLSStatemachine != nil {
1331 if pLSStatemachine.Is("disabled") {
1332 if err := pLSStatemachine.Event("start"); err != nil {
1333 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1334 // maybe try a FSM reset and then again ... - TODO!!!
1335 } else {
1336 /***** LockStateFSM started */
1337 logger.Debugw("LockStateFSM started", log.Fields{
1338 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1339 }
1340 } else {
1341 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1342 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1343 // maybe try a FSM reset and then again ... - TODO!!!
1344 }
1345 } else {
1346 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1347 // maybe try a FSM reset and then again ... - TODO!!!
1348 }
1349}
1350
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001351/* **** Traffic Profile related processing **********/
1352// updateOnuUniTpPath verifies and updates changes in the dh.onuUniTpPath
1353func (dh *DeviceHandler) updateOnuUniTpPath(aUniID uint32, aPathString string) bool {
1354 /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
1355 as also the complete sequence is ensured to 'run to completion' before some new request is accepted
1356 no specific concurrency protection to sOnuPersistentData is required here
1357 */
1358 if existingPath, present := dh.sOnuPersistentData.persUniTpPath[aUniID]; present {
1359 // uni entry already exists
1360 //logger.Debugw(" already exists", log.Fields{"for InstanceId": a_uniInstNo})
1361 if existingPath != aPathString {
1362 if aPathString == "" {
1363 //existing entry to be deleted
1364 logger.Debugw("UniTp path delete", log.Fields{
1365 "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
1366 delete(dh.sOnuPersistentData.persUniTpPath, aUniID)
1367 } else {
1368 //existing entry to be modified
1369 logger.Debugw("UniTp path modify", log.Fields{
1370 "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
1371 dh.sOnuPersistentData.persUniTpPath[aUniID] = aPathString
1372 }
1373 return true
1374 }
1375 //entry already exists
1376 logger.Debugw("UniTp path already exists", log.Fields{
1377 "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
1378 return false
1379 } else {
1380 //uni entry does not exist
1381 if aPathString == "" {
1382 //delete request in non-existing state , accept as no change
1383 logger.Debugw("UniTp path already removed", log.Fields{
1384 "deviceID": dh.deviceID, "uniID": aUniID})
1385 return false
1386 }
1387 //new entry to be set
1388 logger.Debugw("New UniTp path set", log.Fields{
1389 "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
1390 dh.sOnuPersistentData.persUniTpPath[aUniID] = aPathString
1391 return true
1392 }
1393}
1394
1395func (dh *DeviceHandler) configureUniTp(aUniID uint32, aPathString string, wg *sync.WaitGroup) {
1396 defer wg.Done()
1397 logger.Debugw("this would configure the Uni according to TpPath", log.Fields{
1398 "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
1399 //TODO!!!
1400 //this processing requires reading of the TechProfile config data from KV-Store,
1401 // to evaluate the configuration and to start the corresponding OMCI configuation of the UNI port
1402}
1403
1404func (dh *DeviceHandler) updateOnuTpPathKvStore(wg *sync.WaitGroup) {
1405 defer wg.Done()
1406 logger.Debugw("this would update the ONU's TpPath in KVStore", log.Fields{
1407 "deviceID": dh.deviceID})
1408 //TODO!!!
1409 //make use of dh.sOnuPersistentData to store the TpPath to KVStore
1410}
1411
1412// deleteTpRessource removes ressources from the ONU's specified Uni
1413func (dh *DeviceHandler) deleteTpRessource(aUniID uint32, aPathString string,
1414 aRessource resourceEntry, aEntryID uint32, wg *sync.WaitGroup) {
1415 defer wg.Done()
1416 logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
1417 "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString, "ressource": aRessource})
1418 //TODO!!!
1419}
1420
1421func (dh *DeviceHandler) waitForTpCompletion(wg *sync.WaitGroup) {
1422 wg.Wait()
1423 logger.Debug("some TechProfile Processing completed")
1424 dh.tpProcMutex.Unlock() //allow further TP related processing
1425}
1426
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001427/* *********************************************************** */
1428
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001429func genMacFromOctets(aOctets [6]uint8) string {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001430 return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001431 aOctets[5], aOctets[4], aOctets[3],
1432 aOctets[2], aOctets[1], aOctets[0])
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001433}
1434
1435//copied from OLT Adapter: unify centrally ?
1436func macAddressToUint32Array(mac string) []uint32 {
1437 slist := strings.Split(mac, ":")
1438 result := make([]uint32, len(slist))
1439 var err error
1440 var tmp int64
1441 for index, val := range slist {
1442 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
1443 return []uint32{1, 2, 3, 4, 5, 6}
1444 }
1445 result[index] = uint32(tmp)
1446 }
1447 return result
1448}