blob: e5946f403889d3ad5bc77660b09eea95ed9423ab [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
ozgecanetsiafce57b12020-05-25 14:39:35 +0300290func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
291 logger.Debug("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
292 // and disable port
293 // yield self.disable_ports(lock_ports=True, device_disabled=True)
294 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "OmciAdminLock"); err != nil {
295 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
296 }
297
298 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
299 voltha.OperStatus_UNKNOWN); err != nil {
300 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
301 }
302}
303
304func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
305 logger.Debug("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
306 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
307 voltha.OperStatus_ACTIVE); err != nil {
308 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
309 }
310
311 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "InitialMibDownloaded"); err != nil {
312 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
313 }
314 // and enable port
315 // yield self.enable_ports(device)
316}
317
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000318func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
319 portNo int64) (*ic.PortCapability, error) {
320 logger.Debugw("GetOfpPortInfo start", log.Fields{"deviceID": device.Id, "portNo": portNo})
321
322 //function body as per OLTAdapter handler code
323 // adapted with values from py dapter code
324 if pUniPort, exist := dh.uniEntityMap[uint32(portNo)]; exist {
325 var macOctets [6]uint8
326 macOctets[5] = 0x08
327 macOctets[4] = uint8(dh.ponPortNumber >> 8)
328 macOctets[3] = uint8(dh.ponPortNumber)
329 macOctets[2] = uint8(portNo >> 16)
330 macOctets[1] = uint8(portNo >> 8)
331 macOctets[0] = uint8(portNo)
332 hwAddr := genMacFromOctets(macOctets)
333 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
334 name := device.SerialNumber + "-" + strconv.FormatUint(uint64(pUniPort.macBpNo), 10)
335 ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
336 if pUniPort.operState == vc.OperStatus_ACTIVE {
337 ofUniPortState = of.OfpPortState_OFPPS_LIVE
338 }
339 logger.Debugw("setting LogicalPort", log.Fields{"with-name": name,
340 "withUniPort": pUniPort.name, "withMacBase": hwAddr, "OperState": ofUniPortState})
341
342 return &ic.PortCapability{
343 Port: &voltha.LogicalPort{
344 OfpPort: &of.OfpPort{
345 Name: name,
346 //HwAddr: macAddressToUint32Array(dh.device.MacAddress),
347 HwAddr: macAddressToUint32Array(hwAddr),
348 Config: 0,
349 State: uint32(ofUniPortState),
350 Curr: capacity,
351 Advertised: capacity,
352 Peer: capacity,
353 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
354 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
355 },
356 DeviceId: device.Id,
357 DevicePortNo: uint32(portNo),
358 },
359 }, nil
360 }
361 logger.Warnw("No UniPort found - abort", log.Fields{"for PortNo": uint32(portNo)})
362 return nil, errors.New("UniPort not found")
363}
364
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000365// DeviceHandler methods that implement the adapters interface requests## end #########
366// #####################################################################################
367
368// ################ to be updated acc. needs of ONU Device ########################
369// DeviceHandler StateMachine related state transition methods ##### begin #########
370
371func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
372 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})
373}
374
375// doStateInit provides the device update to the core
376func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
377
378 logger.Debug("doStateInit-started")
379 var err error
380
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000381 // populate what we know. rest comes later after mib sync
382 dh.device.Root = false
383 dh.device.Vendor = "OpenONU"
384 dh.device.Model = "go"
385 dh.device.Reason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000386
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000387 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000388 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
389
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000390 dh.parentId = dh.device.ParentId
391 dh.ponPortNumber = dh.device.ParentPortNo
392
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000393 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
394 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
395 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
396 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
397 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000398 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000399
400 /*
401 self._pon = PonPort.create(self, self._pon_port_number)
402 self._pon.add_peer(self.parent_id, self._pon_port_number)
403 self.logger.debug('adding-pon-port-to-agent',
404 type=self._pon.get_port().type,
405 admin_state=self._pon.get_port().admin_state,
406 oper_status=self._pon.get_port().oper_status,
407 )
408 */
409 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000410 var ponPortNo uint32 = 1
411 if dh.ponPortNumber != 0 {
412 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000413 }
414
415 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000416 PortNo: ponPortNo,
417 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000418 Type: voltha.Port_PON_ONU,
419 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000420 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
421 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000422 }
423 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
424 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
425 e.Cancel(err)
426 return
427 }
428 logger.Debug("doStateInit-done")
429}
430
431// postInit setups the DeviceEntry for the conerned device
432func (dh *DeviceHandler) postInit(e *fsm.Event) {
433
434 logger.Debug("postInit-started")
435 var err error
436 /*
437 dh.Client = oop.NewOpenoltClient(dh.clientCon)
438 dh.pTransitionMap.Handle(ctx, GrpcConnected)
439 return nil
440 */
441 if err = dh.Add_OnuDeviceEntry(context.TODO()); err != nil {
442 logger.Fatalf("Device FSM: Add_OnuDeviceEntry-failed-%s", err)
443 e.Cancel(err)
444 return
445 }
446
447 /*
448 ############################################################################
449 # Setup Alarm handler
450 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
451 device.serial_number)
452 ############################################################################
453 # Setup PM configuration for this device
454 # Pass in ONU specific options
455 kwargs = {
456 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
457 'heartbeat': self.heartbeat,
458 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
459 }
460 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
461 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
462 self.logical_device_id, device.serial_number,
463 grouped=True, freq_override=False, **kwargs)
464 pm_config = self._pm_metrics.make_proto()
465 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
466 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
467 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
468
469 # Note, ONU ID and UNI intf set in add_uni_port method
470 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
471 ani_ports=[self._pon])
472
473 # Code to Run OMCI Test Action
474 kwargs_omci_test_action = {
475 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
476 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
477 }
478 serial_number = device.serial_number
479 self._test_request = OmciTestRequest(self.core_proxy,
480 self.omci_agent, self.device_id,
481 AniG, serial_number,
482 self.logical_device_id,
483 exclusive=False,
484 **kwargs_omci_test_action)
485
486 self.enabled = True
487 else:
488 self.logger.info('onu-already-activated')
489 */
490 logger.Debug("postInit-done")
491}
492
493// doStateConnected get the device info and update to voltha core
494// for comparison of the original method (not that easy to uncomment): compare here:
495// voltha-openolt-adapter/adaptercore/device_handler.go
496// -> this one obviously initiates all communication interfaces of the device ...?
497func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
498
499 logger.Debug("doStateConnected-started")
500 var err error
501 err = errors.New("Device FSM: function not implemented yet!")
502 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000503 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700504 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000505}
506
507// doStateUp handle the onu up indication and update to voltha core
508func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
509
510 logger.Debug("doStateUp-started")
511 var err error
512 err = errors.New("Device FSM: function not implemented yet!")
513 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000514 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700515 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000516
517 /*
518 // Synchronous call to update device state - this method is run in its own go routine
519 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
520 voltha.OperStatus_ACTIVE); err != nil {
521 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
522 return err
523 }
524 return nil
525 */
526}
527
528// doStateDown handle the onu down indication
529func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
530
531 logger.Debug("doStateDown-started")
532 var err error
533
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000534 device := dh.device
535 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000536 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000537 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000538 e.Cancel(err)
539 return
540 }
541
542 cloned := proto.Clone(device).(*voltha.Device)
543 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
544 /*
545 // Update the all ports state on that device to disable
546 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
547 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
548 return er
549 }
550
551 //Update the device oper state and connection status
552 cloned.OperStatus = voltha.OperStatus_UNKNOWN
553 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
554 dh.device = cloned
555
556 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
557 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
558 return er
559 }
560
561 //get the child device for the parent device
562 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
563 if err != nil {
564 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
565 return err
566 }
567 for _, onuDevice := range onuDevices.Items {
568
569 // Update onu state as down in onu adapter
570 onuInd := oop.OnuIndication{}
571 onuInd.OperState = "down"
572 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
573 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
574 if er != nil {
575 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
576 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
577 //Do not return here and continue to process other ONUs
578 }
579 }
580 // * Discovered ONUs entries need to be cleared , since after OLT
581 // is up, it starts sending discovery indications again* /
582 dh.discOnus = sync.Map{}
583 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
584 return nil
585 */
586 err = errors.New("Device FSM: function not implemented yet!")
587 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000588 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700589 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000590}
591
592// DeviceHandler StateMachine related state transition methods ##### end #########
593// #################################################################################
594
595// ###################################################
596// DeviceHandler utility methods ##### begin #########
597
598// Get ONU device entry for this deviceId specific handler
599func (dh *DeviceHandler) GetOnuDeviceEntry() *OnuDeviceEntry {
600 dh.lockDevice.Lock()
601 defer dh.lockDevice.Unlock()
602 if dh.pOnuOmciDevice != nil {
603 logger.Debugw("GetOnuDeviceEntry params:",
604 log.Fields{"onu_device_entry": dh.pOnuOmciDevice, "device_id": dh.pOnuOmciDevice.deviceID,
605 "device_handler": dh.pOnuOmciDevice.baseDeviceHandler, "core_proxy": dh.pOnuOmciDevice.coreProxy, "adapter_proxy": dh.pOnuOmciDevice.adapterProxy})
606 } else {
607 logger.Error("GetOnuDeviceEntry returns nil")
608 }
609 return dh.pOnuOmciDevice
610}
611
612// Set ONU device entry
613func (dh *DeviceHandler) SetOnuDeviceEntry(pDeviceEntry *OnuDeviceEntry) error {
614 dh.lockDevice.Lock()
615 defer dh.lockDevice.Unlock()
616 dh.pOnuOmciDevice = pDeviceEntry
617 return nil
618}
619
620//creates a new ONU device or returns the existing
621func (dh *DeviceHandler) Add_OnuDeviceEntry(ctx context.Context) error {
622 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
623
624 deviceEntry := dh.GetOnuDeviceEntry()
625 if deviceEntry == nil {
626 /* costum_me_map in python code seems always to be None,
627 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
628 /* also no 'clock' argument - usage open ...*/
629 /* and no alarm_db yet (oo.alarm_db) */
630 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh, dh.coreProxy, dh.AdapterProxy,
631 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
632 //error treatment possible //TODO!!!
633 dh.SetOnuDeviceEntry(deviceEntry)
634 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
635 } else {
636 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
637 }
638 // might be updated with some error handling !!!
639 return nil
640}
641
642// doStateInit provides the device update to the core
643func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000644 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
645 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
646
647 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000648
649 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
650 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
651 }
652
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000653 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
654 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
655 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
656 // but I would not know why, and the go code anyway dows not work with the device directly anymore in the OnuDeviceEntry
657 // so let's just try to keep it simple ...
658 /*
659 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
660 if err != nil || device == nil {
661 //TODO: needs to handle error scenarios
662 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
663 return errors.New("Voltha Device not found")
664 }
665 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000666
667 dh.GetOnuDeviceEntry().Start(context.TODO())
668 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
669 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
670 }
671
672 /* this might be a good time for Omci Verify message? */
673 verifyExec := make(chan bool)
674 omci_verify := NewOmciTestRequest(context.TODO(),
675 dh.device.Id, dh.GetOnuDeviceEntry().PDevOmciCC,
676 true, true) //eclusive and allowFailure (anyway not yet checked)
677 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
678
679 /* give the handler some time here to wait for the OMCi verification result
680 after Timeout start and try MibUpload FSM anyway
681 (to prevent stopping on just not supported OMCI verification from ONU) */
682 select {
683 case <-time.After(2 * time.Second):
684 logger.Warn("omci start-verification timed out (continue normal)")
685 case testresult := <-verifyExec:
686 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
687 }
688
689 /* In py code it looks earlier (on activate ..)
690 # Code to Run OMCI Test Action
691 kwargs_omci_test_action = {
692 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
693 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
694 }
695 serial_number = device.serial_number
696 self._test_request = OmciTestRequest(self.core_proxy,
697 self.omci_agent, self.device_id,
698 AniG, serial_number,
699 self.logical_device_id,
700 exclusive=False,
701 **kwargs_omci_test_action)
702 ...
703 # Start test requests after a brief pause
704 if not self._test_request_started:
705 self._test_request_started = True
706 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
707 reactor.callLater(tststart, self._test_request.start_collector)
708
709 */
710 /* which is then: in omci_test_request.py : */
711 /*
712 def start_collector(self, callback=None):
713 """
714 Start the collection loop for an adapter if the frequency > 0
715
716 :param callback: (callable) Function to call to collect PM data
717 """
718 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
719 if callback is None:
720 callback = self.perform_test_omci
721
722 if self.lc is None:
723 self.lc = LoopingCall(callback)
724
725 if self.default_freq > 0:
726 self.lc.start(interval=self.default_freq / 10)
727
728 def perform_test_omci(self):
729 """
730 Perform the initial test request
731 """
732 ani_g_entities = self._device.configuration.ani_g_entities
733 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
734 is not None else None
735 self._entity_id = ani_g_entities_ids[0]
736 self.logger.info('perform-test', entity_class=self._entity_class,
737 entity_id=self._entity_id)
738 try:
739 frame = MEFrame(self._entity_class, self._entity_id, []).test()
740 result = yield self._device.omci_cc.send(frame)
741 if not result.fields['omci_message'].fields['success_code']:
742 self.logger.info('Self-Test Submitted Successfully',
743 code=result.fields[
744 'omci_message'].fields['success_code'])
745 else:
746 raise TestFailure('Test Failure: {}'.format(
747 result.fields['omci_message'].fields['success_code']))
748 except TimeoutError as e:
749 self.deferred.errback(failure.Failure(e))
750
751 except Exception as e:
752 self.logger.exception('perform-test-Error', e=e,
753 class_id=self._entity_class,
754 entity_id=self._entity_id)
755 self.deferred.errback(failure.Failure(e))
756
757 */
758
759 // PM related heartbeat??? !!!TODO....
760 //self._heartbeat.enabled = True
761
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000762 //call MibUploadFSM - transition up to state "in_sync"
763 pMibUlFsm := dh.GetOnuDeviceEntry().pMibUploadFsm.pFsm
764 if pMibUlFsm != nil {
765 if pMibUlFsm.Is("disabled") {
766 if err := pMibUlFsm.Event("start"); err != nil {
767 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
768 return errors.New("Can't go to state starting")
769 } else {
770 logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
771 //Determine ONU status and start/re-start MIB Synchronization tasks
772 //Determine if this ONU has ever synchronized
773 if true { //TODO: insert valid check
774 if err := pMibUlFsm.Event("load_mib_template"); err != nil {
775 logger.Errorw("MibSyncFsm: Can't go to state loading_mib_template", log.Fields{"err": err})
776 return errors.New("Can't go to state loading_mib_template")
777 } else {
778 logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
779 //Find and load a mib template. If not found proceed with mib_upload
780 // callbacks to be handled:
781 // Event("success")
782 // Event("timeout")
783 //no mib template found
784 if true { //TODO: insert valid check
785 if err := pMibUlFsm.Event("upload_mib"); err != nil {
786 logger.Errorw("MibSyncFsm: Can't go to state uploading", log.Fields{"err": err})
787 return errors.New("Can't go to state uploading")
788 } else {
789 logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
790 //Begin full MIB data upload, starting with a MIB RESET
791 // callbacks to be handled:
792 // success: e.Event("success")
793 // failure: e.Event("timeout")
794 }
795 }
796 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000797 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000798 pMibUlFsm.Event("examine_mds")
799 logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
800 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000801 // callbacks to be handled:
802 // Event("success")
803 // Event("timeout")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000804 // Event("mismatch")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000805 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000806 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000807 } else {
808 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
809 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000810 }
811 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000812 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000813 }
814 return nil
815}
816
817func (dh *DeviceHandler) update_interface(onuind *oop.OnuIndication) error {
818 logger.Debug("update_interface-started - not yet implemented")
819 return nil
820}
821
822func (dh *DeviceHandler) DeviceStateUpdate(dev_Event OnuDeviceEvent) {
823 if dev_Event == MibDatabaseSync {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000824 logger.Debugw("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000825 //initiate DevStateUpdate
826 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
827 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{"deviceID": dh.deviceID, "error": err})
828 }
829
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000830 unigMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.UniGClassID]
831 unigInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(unigMap)
832 if ok {
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +0000833 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000834 for _, mgmtEntityId := range unigInstKeys {
835 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID, "UnigMe EntityID": mgmtEntityId})
836 dh.addUniPort(mgmtEntityId, i, UniPPTP)
837 i++
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000838 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000839 } else {
840 logger.Warnw("No UniG instances found!", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000841 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000842
843 /* real Mib download procedure could look somthing like this:
844 ***** but for the moment the FSM is still limited (sending no OMCI) *****
845 ***** thus never reaches 'downloaded' state *****
846 */
847 pMibDlFsm := dh.GetOnuDeviceEntry().pMibDownloadFsm.pFsm
848 if pMibDlFsm != nil {
849 if pMibDlFsm.Is("disabled") {
850 if err := pMibDlFsm.Event("start"); err != nil {
851 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +0000852 // maybe try a FSM reset and then again ... - TODO!!!
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000853 } else {
854 logger.Debug("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
855 // maybe use more specific states here for the specific download steps ...
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +0000856 if err := pMibDlFsm.Event("create_gal"); err != nil {
857 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000858 } else {
859 logger.Debug("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +0000860 //Begin MIB data download (running autonomously)
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000861 }
862 }
863 } else {
864 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +0000865 // maybe try a FSM reset and then again ... - TODO!!!
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000866 }
867 /***** Mib download started */
868 } else {
869 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
870 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000871 } else if dev_Event == MibDownloadDone {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000872 logger.Debugw("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000873 //initiate DevStateUpdate
874 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
875 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
876 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
877 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000878 logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000879 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
880 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
881 log.Fields{"deviceID": dh.deviceID, "error": err})
882 }
883
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000884 go dh.enableUniPortStateUpdate(dh.deviceID) //cmp python yield self.enable_ports()
885
886 raisedTs := time.Now().UnixNano()
887 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000888 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000889 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000890 }
891}
892
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +0000893func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000894 // parameters are IntfId, OnuId, uniId
895 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
896 uint32(a_uniId))
897 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000898 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
899 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000900 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000901 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000902 if pUniPort == nil {
903 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
904 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000905 //store UniPort with the System-PortNumber key
906 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000907 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000908 if err := pUniPort.CreateVolthaPort(dh); err == nil {
909 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
910 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000911 }
912 }
913}
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000914
915// Enable listen on UniPortState changes and update core port state accordingly
916func (dh *DeviceHandler) enableUniPortStateUpdate(a_deviceID string) {
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000917 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
918 // but towards core only the first port active state is signalled
919 // with following remark:
920 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
921 // # load on the core
922
923 // dh.lock_ports(false) ONU port activation via OMCI //TODO!!! not yet supported
924
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000925 for uniNo, uniPort := range dh.uniEntityMap {
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000926 // only if this port is validated for operState transfer}
927 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
928 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
929 uniPort.SetOperState(vc.OperStatus_ACTIVE)
930 //maybe also use getter functions on uniPort - perhaps later ...
931 go dh.coreProxy.PortStateUpdate(context.TODO(), a_deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
932 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000933 }
934}
935
936// ONU_Active/Inactive announcement on system KAFKA bus
937// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
938func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
939 var de voltha.DeviceEvent
940 eventContext := make(map[string]string)
941 //Populating event context
942 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
943 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
944 if err != nil || parentDevice == nil {
945 logger.Errorw("Failed to fetch parent device for OnuEvent",
946 log.Fields{"parentId": dh.parentId, "err": err})
947 }
948 oltSerialNumber := parentDevice.SerialNumber
949
950 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
951 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
952 eventContext["serial-number"] = dh.device.SerialNumber
953 eventContext["olt_serial_number"] = oltSerialNumber
954 eventContext["device_id"] = a_deviceID
955 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
956 logger.Debugw("prepare ONU_ACTIVATED event",
957 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
958
959 /* Populating device event body */
960 de.Context = eventContext
961 de.ResourceId = a_deviceID
962 if a_OperState == voltha.OperStatus_ACTIVE {
963 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
964 de.Description = fmt.Sprintf("%s Event - %s - %s",
965 cEventObjectType, cOnuActivatedEvent, "Raised")
966 } else {
967 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
968 de.Description = fmt.Sprintf("%s Event - %s - %s",
969 cEventObjectType, cOnuActivatedEvent, "Cleared")
970 }
971 /* Send event to KAFKA */
972 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
973 logger.Warnw("could not send ONU_ACTIVATED event",
974 log.Fields{"DeviceId": a_deviceID, "error": err})
975 }
976 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
977 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
978}
979
980/* *********************************************************** */
981
982func genMacFromOctets(a_octets [6]uint8) string {
983 return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
984 a_octets[5], a_octets[4], a_octets[3],
985 a_octets[2], a_octets[1], a_octets[0])
986}
987
988//copied from OLT Adapter: unify centrally ?
989func macAddressToUint32Array(mac string) []uint32 {
990 slist := strings.Split(mac, ":")
991 result := make([]uint32, len(slist))
992 var err error
993 var tmp int64
994 for index, val := range slist {
995 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
996 return []uint32{1, 2, 3, 4, 5, 6}
997 }
998 result[index] = uint32(tmp)
999 }
1000 return result
1001}