blob: e3f74e976efd0f8803f71bdddfdf879ee44d64ce [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
91 pOnuOmciDevice *OnuDeviceEntry
92 exitChannel chan int
93 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +000094 pOnuIndication *oop.OnuIndication
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000095
96 //Client oop.OpenoltClient
97 //clientCon *grpc.ClientConn
98 //flowMgr *OpenOltFlowMgr
99 //eventMgr *OpenOltEventMgr
100 //resourceMgr *rsrcMgr.OpenOltResourceMgr
101
102 //discOnus sync.Map
103 //onus sync.Map
104 //portStats *OpenOltStatisticsMgr
105 //metrics *pmmetrics.PmMetrics
106 stopCollector chan bool
107 stopHeartbeatCheck chan bool
108 activePorts sync.Map
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000109 uniEntityMap map[uint32]*OnuUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000110}
111
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000112//NewDeviceHandler creates a new device handler
113func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *DeviceHandler {
114 var dh DeviceHandler
115 dh.coreProxy = cp
116 dh.AdapterProxy = ap
117 dh.EventProxy = ep
118 cloned := (proto.Clone(device)).(*voltha.Device)
119 dh.deviceID = cloned.Id
120 dh.DeviceType = cloned.Type
121 dh.adminState = "up"
122 dh.device = cloned
123 dh.pOpenOnuAc = adapter
124 dh.exitChannel = make(chan int, 1)
125 dh.lockDevice = sync.RWMutex{}
126 dh.stopCollector = make(chan bool, 2)
127 dh.stopHeartbeatCheck = make(chan bool, 2)
128 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
129 dh.activePorts = sync.Map{}
130 //TODO initialize the support classes.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000131 dh.uniEntityMap = make(map[uint32]*OnuUniPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000132
133 // Device related state machine
134 dh.pDeviceStateFsm = fsm.NewFSM(
135 "null",
136 fsm.Events{
137 {Name: "DeviceInit", Src: []string{"null", "down"}, Dst: "init"},
138 {Name: "GrpcConnected", Src: []string{"init"}, Dst: "connected"},
139 {Name: "GrpcDisconnected", Src: []string{"connected", "down"}, Dst: "init"},
140 {Name: "DeviceUpInd", Src: []string{"connected", "down"}, Dst: "up"},
141 {Name: "DeviceDownInd", Src: []string{"up"}, Dst: "down"},
142 },
143 fsm.Callbacks{
144 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
145 "before_DeviceInit": func(e *fsm.Event) { dh.doStateInit(e) },
146 "after_DeviceInit": func(e *fsm.Event) { dh.postInit(e) },
147 "before_GrpcConnected": func(e *fsm.Event) { dh.doStateConnected(e) },
148 "before_GrpcDisconnected": func(e *fsm.Event) { dh.doStateInit(e) },
149 "after_GrpcDisconnected": func(e *fsm.Event) { dh.postInit(e) },
150 "before_DeviceUpInd": func(e *fsm.Event) { dh.doStateUp(e) },
151 "before_DeviceDownInd": func(e *fsm.Event) { dh.doStateDown(e) },
152 },
153 )
154 return &dh
155}
156
157// start save the device to the data model
158func (dh *DeviceHandler) Start(ctx context.Context) {
159 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "deviceId": dh.deviceID})
160 // Add the initial device to the local model
161 logger.Debug("device-handler-started")
162}
163
164// stop stops the device dh. Not much to do for now
165func (dh *DeviceHandler) stop(ctx context.Context) {
166 logger.Debug("stopping-device-handler")
167 dh.exitChannel <- 1
168}
169
170// ##########################################################################################
171// DeviceHandler methods that implement the adapters interface requests ##### begin #########
172
173//AdoptDevice adopts the OLT device
174func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
175 logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
176
177 logger.Debug("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
178 if dh.pDeviceStateFsm.Is("null") {
179 if err := dh.pDeviceStateFsm.Event("DeviceInit"); err != nil {
180 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
181 }
182 logger.Debug("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
183 } else {
184 logger.Debug("AdoptDevice: Agent/device init already done")
185 }
186
187 /*
188 // Now, set the initial PM configuration for that device
189 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
190 logger.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
191 }
192
193 go startCollector(dh)
194 go startHeartbeatCheck(dh)
195 */
196}
197
198//ProcessInterAdapterMessage sends the proxied messages to the target device
199// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
200// is meant, and then send the unmarshalled omci message to this onu
201func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
202 msgID := msg.Header.Id
203 msgType := msg.Header.Type
204 fromTopic := msg.Header.FromTopic
205 toTopic := msg.Header.ToTopic
206 toDeviceID := msg.Header.ToDeviceId
207 proxyDeviceID := msg.Header.ProxyDeviceId
208 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
209 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
210
211 switch msgType {
212 case ic.InterAdapterMessageType_OMCI_REQUEST:
213 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000214 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000215 omciMsg := &ic.InterAdapterOmciMessage{}
216 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
217 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
218 return err
219 }
220
221 //assuming omci message content is hex coded!
222 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
223 logger.Debugw("inter-adapter-recv-omci",
224 log.Fields{"RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
225 //receive_message(omci_msg.message)
226 return dh.GetOnuDeviceEntry().PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
227 }
228 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
229 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000230 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000231 onu_indication := &oop.OnuIndication{}
232 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
233 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{"error": err})
234 return err
235 }
236
237 onu_operstate := onu_indication.GetOperState()
238 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
239 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
240 "SNR": onu_indication.GetSerialNumber()})
241
242 //interface related functioons might be error checked ....
243 if onu_operstate == "up" {
244 dh.create_interface(onu_indication)
245 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
246 dh.update_interface(onu_indication)
247 } else {
248 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
249 return errors.New("InvalidOperState")
250 }
251 }
252 default:
253 {
254 logger.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
255 return errors.New("unimplemented")
256 }
257 }
258
259 /* form py code:
260 elif request.header.type == InterAdapterMessageType.TECH_PROFILE_DOWNLOAD_REQUEST:
261 tech_msg = InterAdapterTechProfileDownloadMessage()
262 request.body.Unpack(tech_msg)
263 self.logger.debug('inter-adapter-recv-tech-profile', tech_msg=tech_msg)
264
265 self.load_and_configure_tech_profile(tech_msg.uni_id, tech_msg.path)
266
267 elif request.header.type == InterAdapterMessageType.DELETE_GEM_PORT_REQUEST:
268 del_gem_msg = InterAdapterDeleteGemPortMessage()
269 request.body.Unpack(del_gem_msg)
270 self.logger.debug('inter-adapter-recv-del-gem', gem_del_msg=del_gem_msg)
271
272 self.delete_tech_profile(uni_id=del_gem_msg.uni_id,
273 gem_port_id=del_gem_msg.gem_port_id,
274 tp_path=del_gem_msg.tp_path)
275
276 elif request.header.type == InterAdapterMessageType.DELETE_TCONT_REQUEST:
277 del_tcont_msg = InterAdapterDeleteTcontMessage()
278 request.body.Unpack(del_tcont_msg)
279 self.logger.debug('inter-adapter-recv-del-tcont', del_tcont_msg=del_tcont_msg)
280
281 self.delete_tech_profile(uni_id=del_tcont_msg.uni_id,
282 alloc_id=del_tcont_msg.alloc_id,
283 tp_path=del_tcont_msg.tp_path)
284 else:
285 self.logger.error("inter-adapter-unhandled-type", request=request)
286 */
287 return nil
288}
289
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000290func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
291 portNo int64) (*ic.PortCapability, error) {
292 logger.Debugw("GetOfpPortInfo start", log.Fields{"deviceID": device.Id, "portNo": portNo})
293
294 //function body as per OLTAdapter handler code
295 // adapted with values from py dapter code
296 if pUniPort, exist := dh.uniEntityMap[uint32(portNo)]; exist {
297 var macOctets [6]uint8
298 macOctets[5] = 0x08
299 macOctets[4] = uint8(dh.ponPortNumber >> 8)
300 macOctets[3] = uint8(dh.ponPortNumber)
301 macOctets[2] = uint8(portNo >> 16)
302 macOctets[1] = uint8(portNo >> 8)
303 macOctets[0] = uint8(portNo)
304 hwAddr := genMacFromOctets(macOctets)
305 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
306 name := device.SerialNumber + "-" + strconv.FormatUint(uint64(pUniPort.macBpNo), 10)
307 ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
308 if pUniPort.operState == vc.OperStatus_ACTIVE {
309 ofUniPortState = of.OfpPortState_OFPPS_LIVE
310 }
311 logger.Debugw("setting LogicalPort", log.Fields{"with-name": name,
312 "withUniPort": pUniPort.name, "withMacBase": hwAddr, "OperState": ofUniPortState})
313
314 return &ic.PortCapability{
315 Port: &voltha.LogicalPort{
316 OfpPort: &of.OfpPort{
317 Name: name,
318 //HwAddr: macAddressToUint32Array(dh.device.MacAddress),
319 HwAddr: macAddressToUint32Array(hwAddr),
320 Config: 0,
321 State: uint32(ofUniPortState),
322 Curr: capacity,
323 Advertised: capacity,
324 Peer: capacity,
325 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
326 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
327 },
328 DeviceId: device.Id,
329 DevicePortNo: uint32(portNo),
330 },
331 }, nil
332 }
333 logger.Warnw("No UniPort found - abort", log.Fields{"for PortNo": uint32(portNo)})
334 return nil, errors.New("UniPort not found")
335}
336
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000337// DeviceHandler methods that implement the adapters interface requests## end #########
338// #####################################################################################
339
340// ################ to be updated acc. needs of ONU Device ########################
341// DeviceHandler StateMachine related state transition methods ##### begin #########
342
343func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
344 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})
345}
346
347// doStateInit provides the device update to the core
348func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
349
350 logger.Debug("doStateInit-started")
351 var err error
352
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000353 // populate what we know. rest comes later after mib sync
354 dh.device.Root = false
355 dh.device.Vendor = "OpenONU"
356 dh.device.Model = "go"
357 dh.device.Reason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000358
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000359 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000360 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
361
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000362 dh.parentId = dh.device.ParentId
363 dh.ponPortNumber = dh.device.ParentPortNo
364
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000365 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
366 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
367 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
368 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
369 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000370 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000371
372 /*
373 self._pon = PonPort.create(self, self._pon_port_number)
374 self._pon.add_peer(self.parent_id, self._pon_port_number)
375 self.logger.debug('adding-pon-port-to-agent',
376 type=self._pon.get_port().type,
377 admin_state=self._pon.get_port().admin_state,
378 oper_status=self._pon.get_port().oper_status,
379 )
380 */
381 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000382 var ponPortNo uint32 = 1
383 if dh.ponPortNumber != 0 {
384 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000385 }
386
387 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000388 PortNo: ponPortNo,
389 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000390 Type: voltha.Port_PON_ONU,
391 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000392 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
393 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000394 }
395 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
396 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
397 e.Cancel(err)
398 return
399 }
400 logger.Debug("doStateInit-done")
401}
402
403// postInit setups the DeviceEntry for the conerned device
404func (dh *DeviceHandler) postInit(e *fsm.Event) {
405
406 logger.Debug("postInit-started")
407 var err error
408 /*
409 dh.Client = oop.NewOpenoltClient(dh.clientCon)
410 dh.pTransitionMap.Handle(ctx, GrpcConnected)
411 return nil
412 */
413 if err = dh.Add_OnuDeviceEntry(context.TODO()); err != nil {
414 logger.Fatalf("Device FSM: Add_OnuDeviceEntry-failed-%s", err)
415 e.Cancel(err)
416 return
417 }
418
419 /*
420 ############################################################################
421 # Setup Alarm handler
422 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
423 device.serial_number)
424 ############################################################################
425 # Setup PM configuration for this device
426 # Pass in ONU specific options
427 kwargs = {
428 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
429 'heartbeat': self.heartbeat,
430 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
431 }
432 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
433 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
434 self.logical_device_id, device.serial_number,
435 grouped=True, freq_override=False, **kwargs)
436 pm_config = self._pm_metrics.make_proto()
437 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
438 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
439 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
440
441 # Note, ONU ID and UNI intf set in add_uni_port method
442 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
443 ani_ports=[self._pon])
444
445 # Code to Run OMCI Test Action
446 kwargs_omci_test_action = {
447 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
448 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
449 }
450 serial_number = device.serial_number
451 self._test_request = OmciTestRequest(self.core_proxy,
452 self.omci_agent, self.device_id,
453 AniG, serial_number,
454 self.logical_device_id,
455 exclusive=False,
456 **kwargs_omci_test_action)
457
458 self.enabled = True
459 else:
460 self.logger.info('onu-already-activated')
461 */
462 logger.Debug("postInit-done")
463}
464
465// doStateConnected get the device info and update to voltha core
466// for comparison of the original method (not that easy to uncomment): compare here:
467// voltha-openolt-adapter/adaptercore/device_handler.go
468// -> this one obviously initiates all communication interfaces of the device ...?
469func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
470
471 logger.Debug("doStateConnected-started")
472 var err error
473 err = errors.New("Device FSM: function not implemented yet!")
474 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000475 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700476 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000477}
478
479// doStateUp handle the onu up indication and update to voltha core
480func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
481
482 logger.Debug("doStateUp-started")
483 var err error
484 err = errors.New("Device FSM: function not implemented yet!")
485 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000486 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700487 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000488
489 /*
490 // Synchronous call to update device state - this method is run in its own go routine
491 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
492 voltha.OperStatus_ACTIVE); err != nil {
493 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
494 return err
495 }
496 return nil
497 */
498}
499
500// doStateDown handle the onu down indication
501func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
502
503 logger.Debug("doStateDown-started")
504 var err error
505
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000506 device := dh.device
507 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000508 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000509 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000510 e.Cancel(err)
511 return
512 }
513
514 cloned := proto.Clone(device).(*voltha.Device)
515 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
516 /*
517 // Update the all ports state on that device to disable
518 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
519 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
520 return er
521 }
522
523 //Update the device oper state and connection status
524 cloned.OperStatus = voltha.OperStatus_UNKNOWN
525 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
526 dh.device = cloned
527
528 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
529 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
530 return er
531 }
532
533 //get the child device for the parent device
534 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
535 if err != nil {
536 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
537 return err
538 }
539 for _, onuDevice := range onuDevices.Items {
540
541 // Update onu state as down in onu adapter
542 onuInd := oop.OnuIndication{}
543 onuInd.OperState = "down"
544 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
545 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
546 if er != nil {
547 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
548 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
549 //Do not return here and continue to process other ONUs
550 }
551 }
552 // * Discovered ONUs entries need to be cleared , since after OLT
553 // is up, it starts sending discovery indications again* /
554 dh.discOnus = sync.Map{}
555 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
556 return nil
557 */
558 err = errors.New("Device FSM: function not implemented yet!")
559 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000560 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700561 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000562}
563
564// DeviceHandler StateMachine related state transition methods ##### end #########
565// #################################################################################
566
567// ###################################################
568// DeviceHandler utility methods ##### begin #########
569
570// Get ONU device entry for this deviceId specific handler
571func (dh *DeviceHandler) GetOnuDeviceEntry() *OnuDeviceEntry {
572 dh.lockDevice.Lock()
573 defer dh.lockDevice.Unlock()
574 if dh.pOnuOmciDevice != nil {
575 logger.Debugw("GetOnuDeviceEntry params:",
576 log.Fields{"onu_device_entry": dh.pOnuOmciDevice, "device_id": dh.pOnuOmciDevice.deviceID,
577 "device_handler": dh.pOnuOmciDevice.baseDeviceHandler, "core_proxy": dh.pOnuOmciDevice.coreProxy, "adapter_proxy": dh.pOnuOmciDevice.adapterProxy})
578 } else {
579 logger.Error("GetOnuDeviceEntry returns nil")
580 }
581 return dh.pOnuOmciDevice
582}
583
584// Set ONU device entry
585func (dh *DeviceHandler) SetOnuDeviceEntry(pDeviceEntry *OnuDeviceEntry) error {
586 dh.lockDevice.Lock()
587 defer dh.lockDevice.Unlock()
588 dh.pOnuOmciDevice = pDeviceEntry
589 return nil
590}
591
592//creates a new ONU device or returns the existing
593func (dh *DeviceHandler) Add_OnuDeviceEntry(ctx context.Context) error {
594 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
595
596 deviceEntry := dh.GetOnuDeviceEntry()
597 if deviceEntry == nil {
598 /* costum_me_map in python code seems always to be None,
599 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
600 /* also no 'clock' argument - usage open ...*/
601 /* and no alarm_db yet (oo.alarm_db) */
602 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh, dh.coreProxy, dh.AdapterProxy,
603 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
604 //error treatment possible //TODO!!!
605 dh.SetOnuDeviceEntry(deviceEntry)
606 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
607 } else {
608 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
609 }
610 // might be updated with some error handling !!!
611 return nil
612}
613
614// doStateInit provides the device update to the core
615func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000616 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
617 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
618
619 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000620
621 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
622 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
623 }
624
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000625 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
626 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
627 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
628 // but I would not know why, and the go code anyway dows not work with the device directly anymore in the OnuDeviceEntry
629 // so let's just try to keep it simple ...
630 /*
631 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
632 if err != nil || device == nil {
633 //TODO: needs to handle error scenarios
634 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
635 return errors.New("Voltha Device not found")
636 }
637 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000638
639 dh.GetOnuDeviceEntry().Start(context.TODO())
640 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
641 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
642 }
643
644 /* this might be a good time for Omci Verify message? */
645 verifyExec := make(chan bool)
646 omci_verify := NewOmciTestRequest(context.TODO(),
647 dh.device.Id, dh.GetOnuDeviceEntry().PDevOmciCC,
648 true, true) //eclusive and allowFailure (anyway not yet checked)
649 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
650
651 /* give the handler some time here to wait for the OMCi verification result
652 after Timeout start and try MibUpload FSM anyway
653 (to prevent stopping on just not supported OMCI verification from ONU) */
654 select {
655 case <-time.After(2 * time.Second):
656 logger.Warn("omci start-verification timed out (continue normal)")
657 case testresult := <-verifyExec:
658 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
659 }
660
661 /* In py code it looks earlier (on activate ..)
662 # Code to Run OMCI Test Action
663 kwargs_omci_test_action = {
664 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
665 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
666 }
667 serial_number = device.serial_number
668 self._test_request = OmciTestRequest(self.core_proxy,
669 self.omci_agent, self.device_id,
670 AniG, serial_number,
671 self.logical_device_id,
672 exclusive=False,
673 **kwargs_omci_test_action)
674 ...
675 # Start test requests after a brief pause
676 if not self._test_request_started:
677 self._test_request_started = True
678 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
679 reactor.callLater(tststart, self._test_request.start_collector)
680
681 */
682 /* which is then: in omci_test_request.py : */
683 /*
684 def start_collector(self, callback=None):
685 """
686 Start the collection loop for an adapter if the frequency > 0
687
688 :param callback: (callable) Function to call to collect PM data
689 """
690 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
691 if callback is None:
692 callback = self.perform_test_omci
693
694 if self.lc is None:
695 self.lc = LoopingCall(callback)
696
697 if self.default_freq > 0:
698 self.lc.start(interval=self.default_freq / 10)
699
700 def perform_test_omci(self):
701 """
702 Perform the initial test request
703 """
704 ani_g_entities = self._device.configuration.ani_g_entities
705 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
706 is not None else None
707 self._entity_id = ani_g_entities_ids[0]
708 self.logger.info('perform-test', entity_class=self._entity_class,
709 entity_id=self._entity_id)
710 try:
711 frame = MEFrame(self._entity_class, self._entity_id, []).test()
712 result = yield self._device.omci_cc.send(frame)
713 if not result.fields['omci_message'].fields['success_code']:
714 self.logger.info('Self-Test Submitted Successfully',
715 code=result.fields[
716 'omci_message'].fields['success_code'])
717 else:
718 raise TestFailure('Test Failure: {}'.format(
719 result.fields['omci_message'].fields['success_code']))
720 except TimeoutError as e:
721 self.deferred.errback(failure.Failure(e))
722
723 except Exception as e:
724 self.logger.exception('perform-test-Error', e=e,
725 class_id=self._entity_class,
726 entity_id=self._entity_id)
727 self.deferred.errback(failure.Failure(e))
728
729 */
730
731 // PM related heartbeat??? !!!TODO....
732 //self._heartbeat.enabled = True
733
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000734 //call MibUploadFSM - transition up to state "in_sync"
735 pMibUlFsm := dh.GetOnuDeviceEntry().pMibUploadFsm.pFsm
736 if pMibUlFsm != nil {
737 if pMibUlFsm.Is("disabled") {
738 if err := pMibUlFsm.Event("start"); err != nil {
739 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
740 return errors.New("Can't go to state starting")
741 } else {
742 logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
743 //Determine ONU status and start/re-start MIB Synchronization tasks
744 //Determine if this ONU has ever synchronized
745 if true { //TODO: insert valid check
746 if err := pMibUlFsm.Event("load_mib_template"); err != nil {
747 logger.Errorw("MibSyncFsm: Can't go to state loading_mib_template", log.Fields{"err": err})
748 return errors.New("Can't go to state loading_mib_template")
749 } else {
750 logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
751 //Find and load a mib template. If not found proceed with mib_upload
752 // callbacks to be handled:
753 // Event("success")
754 // Event("timeout")
755 //no mib template found
756 if true { //TODO: insert valid check
757 if err := pMibUlFsm.Event("upload_mib"); err != nil {
758 logger.Errorw("MibSyncFsm: Can't go to state uploading", log.Fields{"err": err})
759 return errors.New("Can't go to state uploading")
760 } else {
761 logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
762 //Begin full MIB data upload, starting with a MIB RESET
763 // callbacks to be handled:
764 // success: e.Event("success")
765 // failure: e.Event("timeout")
766 }
767 }
768 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000769 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000770 pMibUlFsm.Event("examine_mds")
771 logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
772 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000773 // callbacks to be handled:
774 // Event("success")
775 // Event("timeout")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000776 // Event("mismatch")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000777 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000778 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000779 } else {
780 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
781 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000782 }
783 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000784 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000785 }
786 return nil
787}
788
789func (dh *DeviceHandler) update_interface(onuind *oop.OnuIndication) error {
790 logger.Debug("update_interface-started - not yet implemented")
791 return nil
792}
793
794func (dh *DeviceHandler) DeviceStateUpdate(dev_Event OnuDeviceEvent) {
795 if dev_Event == MibDatabaseSync {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000796 logger.Debugw("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000797 //initiate DevStateUpdate
798 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
799 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{"deviceID": dh.deviceID, "error": err})
800 }
801
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000802 unigMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.UniGClassID]
803 unigInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(unigMap)
804 if ok {
805 i := uint16(0)
806 for _, mgmtEntityId := range unigInstKeys {
807 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID, "UnigMe EntityID": mgmtEntityId})
808 dh.addUniPort(mgmtEntityId, i, UniPPTP)
809 i++
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000810 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000811 } else {
812 logger.Warnw("No UniG instances found!", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000813 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000814
815 /* real Mib download procedure could look somthing like this:
816 ***** but for the moment the FSM is still limited (sending no OMCI) *****
817 ***** thus never reaches 'downloaded' state *****
818 */
819 pMibDlFsm := dh.GetOnuDeviceEntry().pMibDownloadFsm.pFsm
820 if pMibDlFsm != nil {
821 if pMibDlFsm.Is("disabled") {
822 if err := pMibDlFsm.Event("start"); err != nil {
823 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
824 // maybe try a FSM restart and then again ... - TODO!!!
825 } else {
826 logger.Debug("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
827 // maybe use more specific states here for the specific download steps ...
828 if err := pMibDlFsm.Event("download_mib"); err != nil {
829 logger.Errorw("MibDownloadFsm: Can't go to state downloading", log.Fields{"err": err})
830 } else {
831 logger.Debug("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
832 //Begin MIB data download
833 }
834 }
835 } else {
836 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
837 }
838 /***** Mib download started */
839 } else {
840 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
841 }
842
843 //shortcut code to fake download-done!!!: TODO!!! to be removed with complete DL FSM
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000844 go dh.GetOnuDeviceEntry().transferSystemEvent(MibDownloadDone)
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000845
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000846 } else if dev_Event == MibDownloadDone {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000847 logger.Debugw("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000848 //initiate DevStateUpdate
849 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
850 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
851 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
852 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000853 logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000854 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
855 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
856 log.Fields{"deviceID": dh.deviceID, "error": err})
857 }
858
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000859 go dh.enableUniPortStateUpdate(dh.deviceID) //cmp python yield self.enable_ports()
860
861 raisedTs := time.Now().UnixNano()
862 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000863 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000864 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000865 }
866}
867
868func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint16, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000869 // parameters are IntfId, OnuId, uniId
870 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
871 uint32(a_uniId))
872 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000873 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
874 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000875 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000876 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000877 if pUniPort == nil {
878 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
879 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000880 //store UniPort with the System-PortNumber key
881 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000882 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000883 if err := pUniPort.CreateVolthaPort(dh); err == nil {
884 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
885 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000886 }
887 }
888}
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000889
890// Enable listen on UniPortState changes and update core port state accordingly
891func (dh *DeviceHandler) enableUniPortStateUpdate(a_deviceID string) {
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000892 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
893 // but towards core only the first port active state is signalled
894 // with following remark:
895 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
896 // # load on the core
897
898 // dh.lock_ports(false) ONU port activation via OMCI //TODO!!! not yet supported
899
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000900 for uniNo, uniPort := range dh.uniEntityMap {
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000901 // only if this port is validated for operState transfer}
902 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
903 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
904 uniPort.SetOperState(vc.OperStatus_ACTIVE)
905 //maybe also use getter functions on uniPort - perhaps later ...
906 go dh.coreProxy.PortStateUpdate(context.TODO(), a_deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
907 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000908 }
909}
910
911// ONU_Active/Inactive announcement on system KAFKA bus
912// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
913func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
914 var de voltha.DeviceEvent
915 eventContext := make(map[string]string)
916 //Populating event context
917 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
918 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
919 if err != nil || parentDevice == nil {
920 logger.Errorw("Failed to fetch parent device for OnuEvent",
921 log.Fields{"parentId": dh.parentId, "err": err})
922 }
923 oltSerialNumber := parentDevice.SerialNumber
924
925 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
926 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
927 eventContext["serial-number"] = dh.device.SerialNumber
928 eventContext["olt_serial_number"] = oltSerialNumber
929 eventContext["device_id"] = a_deviceID
930 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
931 logger.Debugw("prepare ONU_ACTIVATED event",
932 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
933
934 /* Populating device event body */
935 de.Context = eventContext
936 de.ResourceId = a_deviceID
937 if a_OperState == voltha.OperStatus_ACTIVE {
938 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
939 de.Description = fmt.Sprintf("%s Event - %s - %s",
940 cEventObjectType, cOnuActivatedEvent, "Raised")
941 } else {
942 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
943 de.Description = fmt.Sprintf("%s Event - %s - %s",
944 cEventObjectType, cOnuActivatedEvent, "Cleared")
945 }
946 /* Send event to KAFKA */
947 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
948 logger.Warnw("could not send ONU_ACTIVATED event",
949 log.Fields{"DeviceId": a_deviceID, "error": err})
950 }
951 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
952 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
953}
954
955/* *********************************************************** */
956
957func genMacFromOctets(a_octets [6]uint8) string {
958 return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
959 a_octets[5], a_octets[4], a_octets[3],
960 a_octets[2], a_octets[1], a_octets[0])
961}
962
963//copied from OLT Adapter: unify centrally ?
964func macAddressToUint32Array(mac string) []uint32 {
965 slist := strings.Split(mac, ":")
966 result := make([]uint32, len(slist))
967 var err error
968 var tmp int64
969 for index, val := range slist {
970 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
971 return []uint32{1, 2, 3, 4, 5, 6}
972 }
973 result[index] = uint32(tmp)
974 }
975 return result
976}