blob: 44a5b6a54788273b2da24f5f42b63ce620c975fa [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 Hildebrandt0f9b88d2020-04-20 13:33:25 +000073//DeviceHandler will interact with the ONU ? device.
74type DeviceHandler struct {
75 deviceID string
76 DeviceType string
77 adminState string
78 device *voltha.Device
79 logicalDeviceID string
80 ProxyAddressID string
81 ProxyAddressType string
Holger Hildebrandt24d51952020-05-04 14:03:42 +000082 parentId string
83 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000084
85 coreProxy adapterif.CoreProxy
86 AdapterProxy adapterif.AdapterProxy
87 EventProxy adapterif.EventProxy
88 pOpenOnuAc *OpenONUAC
89 pDeviceStateFsm *fsm.FSM
90 pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +000091 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000092 pOnuOmciDevice *OnuDeviceEntry
93 exitChannel chan int
94 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +000095 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +000096 deviceReason string
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000097 pLockStateFsm *LockStateFsm
98 pUnlockStateFsm *LockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000099
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000100 //flowMgr *OpenOltFlowMgr
101 //eventMgr *OpenOltEventMgr
102 //resourceMgr *rsrcMgr.OpenOltResourceMgr
103
104 //discOnus sync.Map
105 //onus sync.Map
106 //portStats *OpenOltStatisticsMgr
107 //metrics *pmmetrics.PmMetrics
108 stopCollector chan bool
109 stopHeartbeatCheck chan bool
110 activePorts sync.Map
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000111 uniEntityMap map[uint32]*OnuUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000112}
113
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000114//NewDeviceHandler creates a new device handler
115func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *DeviceHandler {
116 var dh DeviceHandler
117 dh.coreProxy = cp
118 dh.AdapterProxy = ap
119 dh.EventProxy = ep
120 cloned := (proto.Clone(device)).(*voltha.Device)
121 dh.deviceID = cloned.Id
122 dh.DeviceType = cloned.Type
123 dh.adminState = "up"
124 dh.device = cloned
125 dh.pOpenOnuAc = adapter
126 dh.exitChannel = make(chan int, 1)
127 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000128 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000129 dh.stopCollector = make(chan bool, 2)
130 dh.stopHeartbeatCheck = make(chan bool, 2)
131 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
132 dh.activePorts = sync.Map{}
133 //TODO initialize the support classes.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000134 dh.uniEntityMap = make(map[uint32]*OnuUniPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000135
136 // Device related state machine
137 dh.pDeviceStateFsm = fsm.NewFSM(
138 "null",
139 fsm.Events{
140 {Name: "DeviceInit", Src: []string{"null", "down"}, Dst: "init"},
141 {Name: "GrpcConnected", Src: []string{"init"}, Dst: "connected"},
142 {Name: "GrpcDisconnected", Src: []string{"connected", "down"}, Dst: "init"},
143 {Name: "DeviceUpInd", Src: []string{"connected", "down"}, Dst: "up"},
144 {Name: "DeviceDownInd", Src: []string{"up"}, Dst: "down"},
145 },
146 fsm.Callbacks{
147 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
148 "before_DeviceInit": func(e *fsm.Event) { dh.doStateInit(e) },
149 "after_DeviceInit": func(e *fsm.Event) { dh.postInit(e) },
150 "before_GrpcConnected": func(e *fsm.Event) { dh.doStateConnected(e) },
151 "before_GrpcDisconnected": func(e *fsm.Event) { dh.doStateInit(e) },
152 "after_GrpcDisconnected": func(e *fsm.Event) { dh.postInit(e) },
153 "before_DeviceUpInd": func(e *fsm.Event) { dh.doStateUp(e) },
154 "before_DeviceDownInd": func(e *fsm.Event) { dh.doStateDown(e) },
155 },
156 )
157 return &dh
158}
159
160// start save the device to the data model
161func (dh *DeviceHandler) Start(ctx context.Context) {
162 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "deviceId": dh.deviceID})
163 // Add the initial device to the local model
164 logger.Debug("device-handler-started")
165}
166
167// stop stops the device dh. Not much to do for now
168func (dh *DeviceHandler) stop(ctx context.Context) {
169 logger.Debug("stopping-device-handler")
170 dh.exitChannel <- 1
171}
172
173// ##########################################################################################
174// DeviceHandler methods that implement the adapters interface requests ##### begin #########
175
176//AdoptDevice adopts the OLT device
177func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
178 logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
179
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000180 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000181 if dh.pDeviceStateFsm.Is("null") {
182 if err := dh.pDeviceStateFsm.Event("DeviceInit"); err != nil {
183 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
184 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000185 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000186 } else {
187 logger.Debug("AdoptDevice: Agent/device init already done")
188 }
189
190 /*
191 // Now, set the initial PM configuration for that device
192 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
193 logger.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
194 }
195
196 go startCollector(dh)
197 go startHeartbeatCheck(dh)
198 */
199}
200
201//ProcessInterAdapterMessage sends the proxied messages to the target device
202// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
203// is meant, and then send the unmarshalled omci message to this onu
204func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
205 msgID := msg.Header.Id
206 msgType := msg.Header.Type
207 fromTopic := msg.Header.FromTopic
208 toTopic := msg.Header.ToTopic
209 toDeviceID := msg.Header.ToDeviceId
210 proxyDeviceID := msg.Header.ProxyDeviceId
211 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
212 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
213
214 switch msgType {
215 case ic.InterAdapterMessageType_OMCI_REQUEST:
216 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000217 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000218 omciMsg := &ic.InterAdapterOmciMessage{}
219 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
220 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
221 return err
222 }
223
224 //assuming omci message content is hex coded!
225 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
226 logger.Debugw("inter-adapter-recv-omci",
227 log.Fields{"RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
228 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000229 pDevEntry := dh.GetOnuDeviceEntry(true)
230 if pDevEntry != nil {
231 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
232 } else {
233 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
234 return errors.New("No valid OnuDevice")
235 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000236 }
237 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
238 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000239 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000240 onu_indication := &oop.OnuIndication{}
241 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
242 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{"error": err})
243 return err
244 }
245
246 onu_operstate := onu_indication.GetOperState()
247 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
248 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
249 "SNR": onu_indication.GetSerialNumber()})
250
mpagenko3af1f032020-06-10 08:53:41 +0000251 //interface related functions might be error checked ....
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000252 if onu_operstate == "up" {
253 dh.create_interface(onu_indication)
254 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
mpagenko3af1f032020-06-10 08:53:41 +0000255 dh.updateInterface(onu_indication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000256 } else {
257 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
258 return errors.New("InvalidOperState")
259 }
260 }
261 default:
262 {
263 logger.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
264 return errors.New("unimplemented")
265 }
266 }
267
268 /* form py code:
269 elif request.header.type == InterAdapterMessageType.TECH_PROFILE_DOWNLOAD_REQUEST:
270 tech_msg = InterAdapterTechProfileDownloadMessage()
271 request.body.Unpack(tech_msg)
272 self.logger.debug('inter-adapter-recv-tech-profile', tech_msg=tech_msg)
273
274 self.load_and_configure_tech_profile(tech_msg.uni_id, tech_msg.path)
275
276 elif request.header.type == InterAdapterMessageType.DELETE_GEM_PORT_REQUEST:
277 del_gem_msg = InterAdapterDeleteGemPortMessage()
278 request.body.Unpack(del_gem_msg)
279 self.logger.debug('inter-adapter-recv-del-gem', gem_del_msg=del_gem_msg)
280
281 self.delete_tech_profile(uni_id=del_gem_msg.uni_id,
282 gem_port_id=del_gem_msg.gem_port_id,
283 tp_path=del_gem_msg.tp_path)
284
285 elif request.header.type == InterAdapterMessageType.DELETE_TCONT_REQUEST:
286 del_tcont_msg = InterAdapterDeleteTcontMessage()
287 request.body.Unpack(del_tcont_msg)
288 self.logger.debug('inter-adapter-recv-del-tcont', del_tcont_msg=del_tcont_msg)
289
290 self.delete_tech_profile(uni_id=del_tcont_msg.uni_id,
291 alloc_id=del_tcont_msg.alloc_id,
292 tp_path=del_tcont_msg.tp_path)
293 else:
294 self.logger.error("inter-adapter-unhandled-type", request=request)
295 */
296 return nil
297}
298
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000299//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000300// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
301// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300302func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000303 logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
304
mpagenko3af1f032020-06-10 08:53:41 +0000305 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
306 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
307 if dh.deviceReason != "omci-admin-lock" {
308 // disable UNI ports/ONU
309 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
310 // here the result of the processing is not checked (trusted in background) *****
311 if dh.pLockStateFsm == nil {
312 dh.createUniLockFsm(true, UniAdminStateDone)
313 } else { //LockStateFSM already init
314 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
315 dh.runUniLockFsm(true)
316 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300317
mpagenko3af1f032020-06-10 08:53:41 +0000318 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
319 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
320 }
321 dh.deviceReason = "omci-admin-lock"
322 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
323 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
324 voltha.OperStatus_UNKNOWN); err != nil {
325 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
326 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300327 }
328}
329
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000330//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000331// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
332// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300333func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000334 logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000335
336 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300337 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
338 voltha.OperStatus_ACTIVE); err != nil {
339 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
340 }
341
mpagenko3af1f032020-06-10 08:53:41 +0000342 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000343 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
ozgecanetsiafce57b12020-05-25 14:39:35 +0300344 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
345 }
mpagenko3af1f032020-06-10 08:53:41 +0000346 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000347
348 // enable ONU/UNI ports
349 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
350 // here the result of the processing is not checked (trusted in background) *****
351 if dh.pUnlockStateFsm == nil {
352 dh.createUniLockFsm(false, UniAdminStateDone)
353 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000354 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000355 dh.runUniLockFsm(false)
356 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300357}
358
mpagenko3af1f032020-06-10 08:53:41 +0000359//GetOfpPortInfo returns the Voltha PortCapabilty with the logical port
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000360func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
361 portNo int64) (*ic.PortCapability, error) {
362 logger.Debugw("GetOfpPortInfo start", log.Fields{"deviceID": device.Id, "portNo": portNo})
363
364 //function body as per OLTAdapter handler code
365 // adapted with values from py dapter code
366 if pUniPort, exist := dh.uniEntityMap[uint32(portNo)]; exist {
367 var macOctets [6]uint8
368 macOctets[5] = 0x08
369 macOctets[4] = uint8(dh.ponPortNumber >> 8)
370 macOctets[3] = uint8(dh.ponPortNumber)
371 macOctets[2] = uint8(portNo >> 16)
372 macOctets[1] = uint8(portNo >> 8)
373 macOctets[0] = uint8(portNo)
374 hwAddr := genMacFromOctets(macOctets)
375 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
376 name := device.SerialNumber + "-" + strconv.FormatUint(uint64(pUniPort.macBpNo), 10)
377 ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
378 if pUniPort.operState == vc.OperStatus_ACTIVE {
379 ofUniPortState = of.OfpPortState_OFPPS_LIVE
380 }
381 logger.Debugw("setting LogicalPort", log.Fields{"with-name": name,
382 "withUniPort": pUniPort.name, "withMacBase": hwAddr, "OperState": ofUniPortState})
383
384 return &ic.PortCapability{
385 Port: &voltha.LogicalPort{
386 OfpPort: &of.OfpPort{
387 Name: name,
388 //HwAddr: macAddressToUint32Array(dh.device.MacAddress),
389 HwAddr: macAddressToUint32Array(hwAddr),
390 Config: 0,
391 State: uint32(ofUniPortState),
392 Curr: capacity,
393 Advertised: capacity,
394 Peer: capacity,
395 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
396 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
397 },
398 DeviceId: device.Id,
399 DevicePortNo: uint32(portNo),
400 },
401 }, nil
402 }
403 logger.Warnw("No UniPort found - abort", log.Fields{"for PortNo": uint32(portNo)})
404 return nil, errors.New("UniPort not found")
405}
406
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000407// DeviceHandler methods that implement the adapters interface requests## end #########
408// #####################################################################################
409
410// ################ to be updated acc. needs of ONU Device ########################
411// DeviceHandler StateMachine related state transition methods ##### begin #########
412
413func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
414 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})
415}
416
417// doStateInit provides the device update to the core
418func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
419
420 logger.Debug("doStateInit-started")
421 var err error
422
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000423 // populate what we know. rest comes later after mib sync
424 dh.device.Root = false
425 dh.device.Vendor = "OpenONU"
426 dh.device.Model = "go"
427 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000428 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000429
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000430 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000431 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
432
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000433 dh.parentId = dh.device.ParentId
434 dh.ponPortNumber = dh.device.ParentPortNo
435
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000436 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
437 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
438 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
439 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
440 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000441 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000442
443 /*
444 self._pon = PonPort.create(self, self._pon_port_number)
445 self._pon.add_peer(self.parent_id, self._pon_port_number)
446 self.logger.debug('adding-pon-port-to-agent',
447 type=self._pon.get_port().type,
448 admin_state=self._pon.get_port().admin_state,
449 oper_status=self._pon.get_port().oper_status,
450 )
451 */
452 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000453 var ponPortNo uint32 = 1
454 if dh.ponPortNumber != 0 {
455 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000456 }
457
458 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000459 PortNo: ponPortNo,
460 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000461 Type: voltha.Port_PON_ONU,
462 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000463 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
464 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000465 }
466 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
467 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
468 e.Cancel(err)
469 return
470 }
471 logger.Debug("doStateInit-done")
472}
473
474// postInit setups the DeviceEntry for the conerned device
475func (dh *DeviceHandler) postInit(e *fsm.Event) {
476
477 logger.Debug("postInit-started")
478 var err error
479 /*
480 dh.Client = oop.NewOpenoltClient(dh.clientCon)
481 dh.pTransitionMap.Handle(ctx, GrpcConnected)
482 return nil
483 */
mpagenko3af1f032020-06-10 08:53:41 +0000484 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
485 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000486 e.Cancel(err)
487 return
488 }
489
490 /*
491 ############################################################################
492 # Setup Alarm handler
493 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
494 device.serial_number)
495 ############################################################################
496 # Setup PM configuration for this device
497 # Pass in ONU specific options
498 kwargs = {
499 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
500 'heartbeat': self.heartbeat,
501 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
502 }
503 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
504 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
505 self.logical_device_id, device.serial_number,
506 grouped=True, freq_override=False, **kwargs)
507 pm_config = self._pm_metrics.make_proto()
508 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
509 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
510 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
511
512 # Note, ONU ID and UNI intf set in add_uni_port method
513 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
514 ani_ports=[self._pon])
515
516 # Code to Run OMCI Test Action
517 kwargs_omci_test_action = {
518 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
519 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
520 }
521 serial_number = device.serial_number
522 self._test_request = OmciTestRequest(self.core_proxy,
523 self.omci_agent, self.device_id,
524 AniG, serial_number,
525 self.logical_device_id,
526 exclusive=False,
527 **kwargs_omci_test_action)
528
529 self.enabled = True
530 else:
531 self.logger.info('onu-already-activated')
532 */
533 logger.Debug("postInit-done")
534}
535
536// doStateConnected get the device info and update to voltha core
537// for comparison of the original method (not that easy to uncomment): compare here:
538// voltha-openolt-adapter/adaptercore/device_handler.go
539// -> this one obviously initiates all communication interfaces of the device ...?
540func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
541
542 logger.Debug("doStateConnected-started")
543 var err error
544 err = errors.New("Device FSM: function not implemented yet!")
545 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000546 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700547 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000548}
549
550// doStateUp handle the onu up indication and update to voltha core
551func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
552
553 logger.Debug("doStateUp-started")
554 var err error
555 err = errors.New("Device FSM: function not implemented yet!")
556 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000557 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700558 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000559
560 /*
561 // Synchronous call to update device state - this method is run in its own go routine
562 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
563 voltha.OperStatus_ACTIVE); err != nil {
564 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
565 return err
566 }
567 return nil
568 */
569}
570
571// doStateDown handle the onu down indication
572func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
573
574 logger.Debug("doStateDown-started")
575 var err error
576
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000577 device := dh.device
578 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000579 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000580 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000581 e.Cancel(err)
582 return
583 }
584
585 cloned := proto.Clone(device).(*voltha.Device)
586 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
587 /*
588 // Update the all ports state on that device to disable
589 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
590 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
591 return er
592 }
593
594 //Update the device oper state and connection status
595 cloned.OperStatus = voltha.OperStatus_UNKNOWN
596 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
597 dh.device = cloned
598
599 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
600 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
601 return er
602 }
603
604 //get the child device for the parent device
605 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
606 if err != nil {
607 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
608 return err
609 }
610 for _, onuDevice := range onuDevices.Items {
611
612 // Update onu state as down in onu adapter
613 onuInd := oop.OnuIndication{}
614 onuInd.OperState = "down"
615 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
616 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
617 if er != nil {
618 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
619 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
620 //Do not return here and continue to process other ONUs
621 }
622 }
623 // * Discovered ONUs entries need to be cleared , since after OLT
624 // is up, it starts sending discovery indications again* /
625 dh.discOnus = sync.Map{}
626 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
627 return nil
628 */
629 err = errors.New("Device FSM: function not implemented yet!")
630 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000631 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700632 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000633}
634
635// DeviceHandler StateMachine related state transition methods ##### end #########
636// #################################################################################
637
638// ###################################################
639// DeviceHandler utility methods ##### begin #########
640
mpagenko3af1f032020-06-10 08:53:41 +0000641//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
642func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
643 dh.lockDevice.RLock()
644 pOnuDeviceEntry := dh.pOnuOmciDevice
645 if aWait && pOnuDeviceEntry == nil {
646 //keep the read sema short to allow for subsequent write
647 dh.lockDevice.RUnlock()
648 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"deviceID": dh.deviceID})
649 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
650 // so it might be needed to wait here for that event with some timeout
651 select {
652 case <-time.After(60 * time.Second): //timer may be discussed ...
653 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"deviceID": dh.deviceID})
654 return nil
655 case <-dh.deviceEntrySet:
656 logger.Debugw("devicEntry ready now - continue", log.Fields{"deviceID": dh.deviceID})
657 // if written now, we can return the written value without sema
658 return dh.pOnuOmciDevice
659 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000660 }
mpagenko3af1f032020-06-10 08:53:41 +0000661 dh.lockDevice.RUnlock()
662 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000663}
664
mpagenko3af1f032020-06-10 08:53:41 +0000665//SetOnuDeviceEntry sets the ONU device entry within the handler
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000666func (dh *DeviceHandler) SetOnuDeviceEntry(pDeviceEntry *OnuDeviceEntry) error {
667 dh.lockDevice.Lock()
668 defer dh.lockDevice.Unlock()
669 dh.pOnuOmciDevice = pDeviceEntry
670 return nil
671}
672
mpagenko3af1f032020-06-10 08:53:41 +0000673//AddOnuDeviceEntry creates a new ONU device or returns the existing
674func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000675 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
676
mpagenko3af1f032020-06-10 08:53:41 +0000677 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000678 if deviceEntry == nil {
679 /* costum_me_map in python code seems always to be None,
680 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
681 /* also no 'clock' argument - usage open ...*/
682 /* and no alarm_db yet (oo.alarm_db) */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000683 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost, dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
684 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000685 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
686 //error treatment possible //TODO!!!
687 dh.SetOnuDeviceEntry(deviceEntry)
mpagenko3af1f032020-06-10 08:53:41 +0000688 // fire deviceEntry ready event to spread to possibly waiting processing
689 dh.deviceEntrySet <- true
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000690 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
691 } else {
692 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
693 }
694 // might be updated with some error handling !!!
695 return nil
696}
697
698// doStateInit provides the device update to the core
699func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000700 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
701 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
702
703 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000704
mpagenko3af1f032020-06-10 08:53:41 +0000705 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
706 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000707 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
708 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000709 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
710 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
711 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
712 // but I would not know why, and the go code anyway dows not work with the device directly anymore in the OnuDeviceEntry
713 // so let's just try to keep it simple ...
714 /*
715 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
716 if err != nil || device == nil {
717 //TODO: needs to handle error scenarios
718 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
719 return errors.New("Voltha Device not found")
720 }
721 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000722
mpagenko3af1f032020-06-10 08:53:41 +0000723 pDevEntry := dh.GetOnuDeviceEntry(true)
724 if pDevEntry != nil {
725 pDevEntry.Start(context.TODO())
726 } else {
727 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
728 return errors.New("No valid OnuDevice")
729 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000730 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
731 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
732 }
mpagenko3af1f032020-06-10 08:53:41 +0000733 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000734
735 /* this might be a good time for Omci Verify message? */
736 verifyExec := make(chan bool)
737 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000738 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000739 true, true) //eclusive and allowFailure (anyway not yet checked)
740 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
741
742 /* give the handler some time here to wait for the OMCi verification result
743 after Timeout start and try MibUpload FSM anyway
744 (to prevent stopping on just not supported OMCI verification from ONU) */
745 select {
746 case <-time.After(2 * time.Second):
747 logger.Warn("omci start-verification timed out (continue normal)")
748 case testresult := <-verifyExec:
749 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
750 }
751
752 /* In py code it looks earlier (on activate ..)
753 # Code to Run OMCI Test Action
754 kwargs_omci_test_action = {
755 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
756 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
757 }
758 serial_number = device.serial_number
759 self._test_request = OmciTestRequest(self.core_proxy,
760 self.omci_agent, self.device_id,
761 AniG, serial_number,
762 self.logical_device_id,
763 exclusive=False,
764 **kwargs_omci_test_action)
765 ...
766 # Start test requests after a brief pause
767 if not self._test_request_started:
768 self._test_request_started = True
769 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
770 reactor.callLater(tststart, self._test_request.start_collector)
771
772 */
773 /* which is then: in omci_test_request.py : */
774 /*
775 def start_collector(self, callback=None):
776 """
777 Start the collection loop for an adapter if the frequency > 0
778
779 :param callback: (callable) Function to call to collect PM data
780 """
781 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
782 if callback is None:
783 callback = self.perform_test_omci
784
785 if self.lc is None:
786 self.lc = LoopingCall(callback)
787
788 if self.default_freq > 0:
789 self.lc.start(interval=self.default_freq / 10)
790
791 def perform_test_omci(self):
792 """
793 Perform the initial test request
794 """
795 ani_g_entities = self._device.configuration.ani_g_entities
796 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
797 is not None else None
798 self._entity_id = ani_g_entities_ids[0]
799 self.logger.info('perform-test', entity_class=self._entity_class,
800 entity_id=self._entity_id)
801 try:
802 frame = MEFrame(self._entity_class, self._entity_id, []).test()
803 result = yield self._device.omci_cc.send(frame)
804 if not result.fields['omci_message'].fields['success_code']:
805 self.logger.info('Self-Test Submitted Successfully',
806 code=result.fields[
807 'omci_message'].fields['success_code'])
808 else:
809 raise TestFailure('Test Failure: {}'.format(
810 result.fields['omci_message'].fields['success_code']))
811 except TimeoutError as e:
812 self.deferred.errback(failure.Failure(e))
813
814 except Exception as e:
815 self.logger.exception('perform-test-Error', e=e,
816 class_id=self._entity_class,
817 entity_id=self._entity_id)
818 self.deferred.errback(failure.Failure(e))
819
820 */
821
822 // PM related heartbeat??? !!!TODO....
823 //self._heartbeat.enabled = True
824
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000825 //call MibUploadFSM - transition up to state "in_sync"
mpagenko3af1f032020-06-10 08:53:41 +0000826 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000827 if pMibUlFsm != nil {
828 if pMibUlFsm.Is("disabled") {
829 if err := pMibUlFsm.Event("start"); err != nil {
830 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
831 return errors.New("Can't go to state starting")
832 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000833 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000834 //Determine ONU status and start/re-start MIB Synchronization tasks
835 //Determine if this ONU has ever synchronized
836 if true { //TODO: insert valid check
837 if err := pMibUlFsm.Event("load_mib_template"); err != nil {
838 logger.Errorw("MibSyncFsm: Can't go to state loading_mib_template", log.Fields{"err": err})
839 return errors.New("Can't go to state loading_mib_template")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000840 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000841 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000842 pMibUlFsm.Event("examine_mds")
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000843 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000844 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000845 // callbacks to be handled:
846 // Event("success")
847 // Event("timeout")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000848 // Event("mismatch")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000849 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000850 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000851 } else {
852 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
853 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000854 }
855 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000856 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000857 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000858 }
859 return nil
860}
861
mpagenko3af1f032020-06-10 08:53:41 +0000862func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
863 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
864 if dh.deviceReason != "stopping-openomci" {
865 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"deviceID": dh.deviceID})
866 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
867 pDevEntry := dh.GetOnuDeviceEntry(false)
868 if pDevEntry == nil {
869 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
870 return errors.New("No valid OnuDevice")
871 }
872
873 switch dh.deviceReason {
874 case "starting-openomci":
875 { //MIBSync FSM may run
876 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
877 if pMibUlFsm != nil {
878 pMibUlFsm.Event("stop") //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
879 }
880 }
881 case "discovery-mibsync-complete":
882 { //MibDownload may run
883 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
884 if pMibDlFsm != nil {
885 pMibDlFsm.Event("reset")
886 }
887 }
888 default:
889 { //port lock/unlock FSM's may be active
890 if dh.pUnlockStateFsm != nil {
891 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
892 }
893 if dh.pLockStateFsm != nil {
894 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
895 }
896 }
897 //TODO!!! care about PM/Alarm processing once started
898 }
899 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
900 // (mainly the still seperate 'Event states')
901 // so it is questionable, how this is resolved after some possible re-enable
902 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
903
904 //stop/remove(?) the device entry
905 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
906
907 //TODO!!! remove existing traffic profiles
908 /* from py code, if TP's exist, remove them - not yet implemented
909 self._tp = dict()
910 # Let TP download happen again
911 for uni_id in self._tp_service_specific_task:
912 self._tp_service_specific_task[uni_id].clear()
913 for uni_id in self._tech_profile_download_done:
914 self._tech_profile_download_done[uni_id].clear()
915 */
916
917 dh.disableUniPortStateUpdate()
918
919 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
920 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
921 log.Fields{"deviceID": dh.deviceID, "error": err})
922 // abort: system behavior is just unstable ...
923 return err
924 }
925 dh.deviceReason = "stopping-openomci"
926
927 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
928 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
929 logger.Errorw("error-updating-device-state unreachable-discovered",
930 log.Fields{"deviceID": dh.deviceID, "error": err})
931 // abort: system behavior is just unstable ...
932 return err
933 }
934 } else {
935 logger.Debugw("updateInterface - device already stopped", log.Fields{"deviceID": dh.deviceID})
936 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000937 return nil
938}
939
mpagenko3af1f032020-06-10 08:53:41 +0000940//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000941func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
942 switch dev_Event {
943 case MibDatabaseSync:
944 {
945 logger.Infow("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
946 //initiate DevStateUpdate
947 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
948 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
949 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000950 }
mpagenko3af1f032020-06-10 08:53:41 +0000951 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000952
mpagenko3af1f032020-06-10 08:53:41 +0000953 pDevEntry := dh.GetOnuDeviceEntry(false)
954 unigMap, ok := pDevEntry.pOnuDB.meDb[me.UniGClassID]
955 unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(unigMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000956 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
957 if ok {
958 for _, mgmtEntityId := range unigInstKeys {
959 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
960 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
961 dh.addUniPort(mgmtEntityId, i, UniPPTP)
962 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000963 }
964 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000965 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000966 }
mpagenko3af1f032020-06-10 08:53:41 +0000967 veipMap, ok := pDevEntry.pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
968 veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(veipMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000969 if ok {
970 for _, mgmtEntityId := range veipInstKeys {
971 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
972 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
973 dh.addUniPort(mgmtEntityId, i, UniVEIP)
974 i++
975 }
976 } else {
977 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
978 }
979 if i == 0 {
980 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
981 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000982
mpagenko3af1f032020-06-10 08:53:41 +0000983 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
984 * left the code here as comment in case such processing should prove needed unexpectedly
985 // Init Uni Ports to Admin locked state
986 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
987 // *** should generate UniLockStateDone event *****
988 if dh.pLockStateFsm == nil {
989 dh.createUniLockFsm(true, UniLockStateDone)
990 } else { //LockStateFSM already init
991 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
992 dh.runUniLockFsm(true)
993 }
994 }
995 case UniLockStateDone:
996 {
997 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
998 * lockState processing commented out
999 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001000 /* Mib download procedure -
1001 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1002 */
mpagenko3af1f032020-06-10 08:53:41 +00001003 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001004 if pMibDlFsm != nil {
1005 if pMibDlFsm.Is("disabled") {
1006 if err := pMibDlFsm.Event("start"); err != nil {
1007 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1008 // maybe try a FSM reset and then again ... - TODO!!!
1009 } else {
1010 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1011 // maybe use more specific states here for the specific download steps ...
1012 if err := pMibDlFsm.Event("create_gal"); err != nil {
1013 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1014 } else {
1015 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1016 //Begin MIB data download (running autonomously)
1017 }
1018 }
1019 } else {
1020 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1021 // maybe try a FSM reset and then again ... - TODO!!!
1022 }
1023 /***** Mib download started */
1024 } else {
1025 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1026 }
1027 }
1028 case MibDownloadDone:
1029 {
1030 logger.Infow("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
1031 //initiate DevStateUpdate
1032 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1033 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1034 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
1035 }
mpagenko3af1f032020-06-10 08:53:41 +00001036
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001037 logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
1038 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1039 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1040 log.Fields{"deviceID": dh.deviceID, "error": err})
1041 }
mpagenko3af1f032020-06-10 08:53:41 +00001042 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001043
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001044 // *** should generate UniUnlockStateDone event *****
1045 if dh.pUnlockStateFsm == nil {
1046 dh.createUniLockFsm(false, UniUnlockStateDone)
1047 } else { //UnlockStateFSM already init
1048 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1049 dh.runUniLockFsm(false)
1050 }
1051 }
1052 case UniUnlockStateDone:
1053 {
mpagenko3af1f032020-06-10 08:53:41 +00001054 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001055
1056 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
1057 raisedTs := time.Now().UnixNano()
1058 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1059 }
1060 default:
1061 {
1062 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
1063 }
1064 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001065}
1066
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001067func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001068 // parameters are IntfId, OnuId, uniId
1069 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1070 uint32(a_uniId))
1071 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001072 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1073 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001074 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001075 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001076 if pUniPort == nil {
1077 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1078 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001079 //store UniPort with the System-PortNumber key
1080 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001081 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001082 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1083 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1084 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001085 }
1086 }
1087}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001088
mpagenko3af1f032020-06-10 08:53:41 +00001089// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1090func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001091 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1092 // but towards core only the first port active state is signalled
1093 // with following remark:
1094 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1095 // # load on the core
1096
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001097 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001098
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001099 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001100 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001101 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1102 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1103 uniPort.SetOperState(vc.OperStatus_ACTIVE)
1104 //maybe also use getter functions on uniPort - perhaps later ...
mpagenko3af1f032020-06-10 08:53:41 +00001105 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1106 }
1107 }
1108}
1109
1110// Disable UniPortState and update core port state accordingly
1111func (dh *DeviceHandler) disableUniPortStateUpdate() {
1112 // compare enableUniPortStateUpdate() above
1113 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1114 for uniNo, uniPort := range dh.uniEntityMap {
1115 // only if this port is validated for operState transfer
1116 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1117 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1118 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1119 //maybe also use getter functions on uniPort - perhaps later ...
1120 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001121 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001122 }
1123}
1124
1125// ONU_Active/Inactive announcement on system KAFKA bus
1126// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1127func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1128 var de voltha.DeviceEvent
1129 eventContext := make(map[string]string)
1130 //Populating event context
1131 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1132 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1133 if err != nil || parentDevice == nil {
1134 logger.Errorw("Failed to fetch parent device for OnuEvent",
1135 log.Fields{"parentId": dh.parentId, "err": err})
1136 }
1137 oltSerialNumber := parentDevice.SerialNumber
1138
1139 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1140 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1141 eventContext["serial-number"] = dh.device.SerialNumber
1142 eventContext["olt_serial_number"] = oltSerialNumber
1143 eventContext["device_id"] = a_deviceID
1144 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1145 logger.Debugw("prepare ONU_ACTIVATED event",
1146 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1147
1148 /* Populating device event body */
1149 de.Context = eventContext
1150 de.ResourceId = a_deviceID
1151 if a_OperState == voltha.OperStatus_ACTIVE {
1152 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1153 de.Description = fmt.Sprintf("%s Event - %s - %s",
1154 cEventObjectType, cOnuActivatedEvent, "Raised")
1155 } else {
1156 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1157 de.Description = fmt.Sprintf("%s Event - %s - %s",
1158 cEventObjectType, cOnuActivatedEvent, "Cleared")
1159 }
1160 /* Send event to KAFKA */
1161 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1162 logger.Warnw("could not send ONU_ACTIVATED event",
1163 log.Fields{"DeviceId": a_deviceID, "error": err})
1164 }
1165 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1166 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1167}
1168
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001169// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1170func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1171 chLSFsm := make(chan Message, 2048)
1172 var sFsmName string
1173 if aAdminState == true {
1174 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1175 sFsmName = "LockStateFSM"
1176 } else {
1177 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1178 sFsmName = "UnLockStateFSM"
1179 }
mpagenko3af1f032020-06-10 08:53:41 +00001180
1181 pDevEntry := dh.GetOnuDeviceEntry(true)
1182 if pDevEntry == nil {
1183 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1184 return
1185 }
1186 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001187 sFsmName, dh.deviceID, chLSFsm)
1188 if pLSFsm != nil {
1189 if aAdminState == true {
1190 dh.pLockStateFsm = pLSFsm
1191 } else {
1192 dh.pUnlockStateFsm = pLSFsm
1193 }
1194 dh.runUniLockFsm(aAdminState)
1195 } else {
1196 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1197 }
1198}
1199
1200// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1201func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1202 /* Uni Port lock/unlock procedure -
1203 ***** should run via 'adminDone' state and generate the argument requested event *****
1204 */
1205 var pLSStatemachine *fsm.FSM
1206 if aAdminState == true {
1207 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1208 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1209 if (dh.pUnlockStateFsm != nil) &&
1210 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1211 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
1212 }
1213 } else {
1214 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1215 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1216 if (dh.pLockStateFsm != nil) &&
1217 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1218 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
1219 }
1220 }
1221 if pLSStatemachine != nil {
1222 if pLSStatemachine.Is("disabled") {
1223 if err := pLSStatemachine.Event("start"); err != nil {
1224 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1225 // maybe try a FSM reset and then again ... - TODO!!!
1226 } else {
1227 /***** LockStateFSM started */
1228 logger.Debugw("LockStateFSM started", log.Fields{
1229 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1230 }
1231 } else {
1232 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1233 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1234 // maybe try a FSM reset and then again ... - TODO!!!
1235 }
1236 } else {
1237 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1238 // maybe try a FSM reset and then again ... - TODO!!!
1239 }
1240}
1241
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001242/* *********************************************************** */
1243
1244func genMacFromOctets(a_octets [6]uint8) string {
1245 return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
1246 a_octets[5], a_octets[4], a_octets[3],
1247 a_octets[2], a_octets[1], a_octets[0])
1248}
1249
1250//copied from OLT Adapter: unify centrally ?
1251func macAddressToUint32Array(mac string) []uint32 {
1252 slist := strings.Split(mac, ":")
1253 result := make([]uint32, len(slist))
1254 var err error
1255 var tmp int64
1256 for index, val := range slist {
1257 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
1258 return []uint32{1, 2, 3, 4, 5, 6}
1259 }
1260 result[index] = uint32(tmp)
1261 }
1262 return result
1263}