blob: b67ceab501a91a6f54463e9ec3fc0ca5332ec4b5 [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 Hildebrandtccd390c2020-05-29 13:49:04 +000095 pLockStateFsm *LockStateFsm
96 pUnlockStateFsm *LockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000097
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000098 //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
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000177 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000178 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 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000182 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000183 } 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 Hildebrandtccd390c2020-05-29 13:49:04 +0000290//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300291func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000292 logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
293
294 // disable UNI ports/ONU
295 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
296 // here the result of the processing is not checked (trusted in background) *****
297 if dh.pLockStateFsm == nil {
298 dh.createUniLockFsm(true, UniAdminStateDone)
299 } else { //LockStateFSM already init
300 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
301 dh.runUniLockFsm(true)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300302 }
303
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000304 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
305 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
306 }
307 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...
ozgecanetsiafce57b12020-05-25 14:39:35 +0300308 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
309 voltha.OperStatus_UNKNOWN); err != nil {
310 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
311 }
312}
313
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000314//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300315func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000316 logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
317 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...
ozgecanetsiafce57b12020-05-25 14:39:35 +0300318 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
319 voltha.OperStatus_ACTIVE); err != nil {
320 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
321 }
322
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000323 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
ozgecanetsiafce57b12020-05-25 14:39:35 +0300324 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
325 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000326
327 // enable ONU/UNI ports
328 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
329 // here the result of the processing is not checked (trusted in background) *****
330 if dh.pUnlockStateFsm == nil {
331 dh.createUniLockFsm(false, UniAdminStateDone)
332 } else { //UnlockStateFSM already init
333 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
334 dh.runUniLockFsm(false)
335 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300336}
337
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000338func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
339 portNo int64) (*ic.PortCapability, error) {
340 logger.Debugw("GetOfpPortInfo start", log.Fields{"deviceID": device.Id, "portNo": portNo})
341
342 //function body as per OLTAdapter handler code
343 // adapted with values from py dapter code
344 if pUniPort, exist := dh.uniEntityMap[uint32(portNo)]; exist {
345 var macOctets [6]uint8
346 macOctets[5] = 0x08
347 macOctets[4] = uint8(dh.ponPortNumber >> 8)
348 macOctets[3] = uint8(dh.ponPortNumber)
349 macOctets[2] = uint8(portNo >> 16)
350 macOctets[1] = uint8(portNo >> 8)
351 macOctets[0] = uint8(portNo)
352 hwAddr := genMacFromOctets(macOctets)
353 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
354 name := device.SerialNumber + "-" + strconv.FormatUint(uint64(pUniPort.macBpNo), 10)
355 ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
356 if pUniPort.operState == vc.OperStatus_ACTIVE {
357 ofUniPortState = of.OfpPortState_OFPPS_LIVE
358 }
359 logger.Debugw("setting LogicalPort", log.Fields{"with-name": name,
360 "withUniPort": pUniPort.name, "withMacBase": hwAddr, "OperState": ofUniPortState})
361
362 return &ic.PortCapability{
363 Port: &voltha.LogicalPort{
364 OfpPort: &of.OfpPort{
365 Name: name,
366 //HwAddr: macAddressToUint32Array(dh.device.MacAddress),
367 HwAddr: macAddressToUint32Array(hwAddr),
368 Config: 0,
369 State: uint32(ofUniPortState),
370 Curr: capacity,
371 Advertised: capacity,
372 Peer: capacity,
373 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
374 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
375 },
376 DeviceId: device.Id,
377 DevicePortNo: uint32(portNo),
378 },
379 }, nil
380 }
381 logger.Warnw("No UniPort found - abort", log.Fields{"for PortNo": uint32(portNo)})
382 return nil, errors.New("UniPort not found")
383}
384
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000385// DeviceHandler methods that implement the adapters interface requests## end #########
386// #####################################################################################
387
388// ################ to be updated acc. needs of ONU Device ########################
389// DeviceHandler StateMachine related state transition methods ##### begin #########
390
391func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
392 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})
393}
394
395// doStateInit provides the device update to the core
396func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
397
398 logger.Debug("doStateInit-started")
399 var err error
400
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000401 // populate what we know. rest comes later after mib sync
402 dh.device.Root = false
403 dh.device.Vendor = "OpenONU"
404 dh.device.Model = "go"
405 dh.device.Reason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000406
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000407 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000408 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
409
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000410 dh.parentId = dh.device.ParentId
411 dh.ponPortNumber = dh.device.ParentPortNo
412
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000413 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
414 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
415 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
416 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
417 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000418 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000419
420 /*
421 self._pon = PonPort.create(self, self._pon_port_number)
422 self._pon.add_peer(self.parent_id, self._pon_port_number)
423 self.logger.debug('adding-pon-port-to-agent',
424 type=self._pon.get_port().type,
425 admin_state=self._pon.get_port().admin_state,
426 oper_status=self._pon.get_port().oper_status,
427 )
428 */
429 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000430 var ponPortNo uint32 = 1
431 if dh.ponPortNumber != 0 {
432 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000433 }
434
435 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000436 PortNo: ponPortNo,
437 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000438 Type: voltha.Port_PON_ONU,
439 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000440 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
441 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000442 }
443 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
444 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
445 e.Cancel(err)
446 return
447 }
448 logger.Debug("doStateInit-done")
449}
450
451// postInit setups the DeviceEntry for the conerned device
452func (dh *DeviceHandler) postInit(e *fsm.Event) {
453
454 logger.Debug("postInit-started")
455 var err error
456 /*
457 dh.Client = oop.NewOpenoltClient(dh.clientCon)
458 dh.pTransitionMap.Handle(ctx, GrpcConnected)
459 return nil
460 */
461 if err = dh.Add_OnuDeviceEntry(context.TODO()); err != nil {
462 logger.Fatalf("Device FSM: Add_OnuDeviceEntry-failed-%s", err)
463 e.Cancel(err)
464 return
465 }
466
467 /*
468 ############################################################################
469 # Setup Alarm handler
470 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
471 device.serial_number)
472 ############################################################################
473 # Setup PM configuration for this device
474 # Pass in ONU specific options
475 kwargs = {
476 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
477 'heartbeat': self.heartbeat,
478 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
479 }
480 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
481 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
482 self.logical_device_id, device.serial_number,
483 grouped=True, freq_override=False, **kwargs)
484 pm_config = self._pm_metrics.make_proto()
485 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
486 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
487 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
488
489 # Note, ONU ID and UNI intf set in add_uni_port method
490 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
491 ani_ports=[self._pon])
492
493 # Code to Run OMCI Test Action
494 kwargs_omci_test_action = {
495 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
496 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
497 }
498 serial_number = device.serial_number
499 self._test_request = OmciTestRequest(self.core_proxy,
500 self.omci_agent, self.device_id,
501 AniG, serial_number,
502 self.logical_device_id,
503 exclusive=False,
504 **kwargs_omci_test_action)
505
506 self.enabled = True
507 else:
508 self.logger.info('onu-already-activated')
509 */
510 logger.Debug("postInit-done")
511}
512
513// doStateConnected get the device info and update to voltha core
514// for comparison of the original method (not that easy to uncomment): compare here:
515// voltha-openolt-adapter/adaptercore/device_handler.go
516// -> this one obviously initiates all communication interfaces of the device ...?
517func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
518
519 logger.Debug("doStateConnected-started")
520 var err error
521 err = errors.New("Device FSM: function not implemented yet!")
522 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000523 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700524 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000525}
526
527// doStateUp handle the onu up indication and update to voltha core
528func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
529
530 logger.Debug("doStateUp-started")
531 var err error
532 err = errors.New("Device FSM: function not implemented yet!")
533 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000534 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700535 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000536
537 /*
538 // Synchronous call to update device state - this method is run in its own go routine
539 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
540 voltha.OperStatus_ACTIVE); err != nil {
541 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
542 return err
543 }
544 return nil
545 */
546}
547
548// doStateDown handle the onu down indication
549func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
550
551 logger.Debug("doStateDown-started")
552 var err error
553
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000554 device := dh.device
555 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000556 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000557 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000558 e.Cancel(err)
559 return
560 }
561
562 cloned := proto.Clone(device).(*voltha.Device)
563 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
564 /*
565 // Update the all ports state on that device to disable
566 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
567 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
568 return er
569 }
570
571 //Update the device oper state and connection status
572 cloned.OperStatus = voltha.OperStatus_UNKNOWN
573 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
574 dh.device = cloned
575
576 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
577 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
578 return er
579 }
580
581 //get the child device for the parent device
582 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
583 if err != nil {
584 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
585 return err
586 }
587 for _, onuDevice := range onuDevices.Items {
588
589 // Update onu state as down in onu adapter
590 onuInd := oop.OnuIndication{}
591 onuInd.OperState = "down"
592 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
593 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
594 if er != nil {
595 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
596 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
597 //Do not return here and continue to process other ONUs
598 }
599 }
600 // * Discovered ONUs entries need to be cleared , since after OLT
601 // is up, it starts sending discovery indications again* /
602 dh.discOnus = sync.Map{}
603 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
604 return nil
605 */
606 err = errors.New("Device FSM: function not implemented yet!")
607 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000608 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700609 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000610}
611
612// DeviceHandler StateMachine related state transition methods ##### end #########
613// #################################################################################
614
615// ###################################################
616// DeviceHandler utility methods ##### begin #########
617
618// Get ONU device entry for this deviceId specific handler
619func (dh *DeviceHandler) GetOnuDeviceEntry() *OnuDeviceEntry {
620 dh.lockDevice.Lock()
621 defer dh.lockDevice.Unlock()
622 if dh.pOnuOmciDevice != nil {
623 logger.Debugw("GetOnuDeviceEntry params:",
624 log.Fields{"onu_device_entry": dh.pOnuOmciDevice, "device_id": dh.pOnuOmciDevice.deviceID,
625 "device_handler": dh.pOnuOmciDevice.baseDeviceHandler, "core_proxy": dh.pOnuOmciDevice.coreProxy, "adapter_proxy": dh.pOnuOmciDevice.adapterProxy})
626 } else {
627 logger.Error("GetOnuDeviceEntry returns nil")
628 }
629 return dh.pOnuOmciDevice
630}
631
632// Set ONU device entry
633func (dh *DeviceHandler) SetOnuDeviceEntry(pDeviceEntry *OnuDeviceEntry) error {
634 dh.lockDevice.Lock()
635 defer dh.lockDevice.Unlock()
636 dh.pOnuOmciDevice = pDeviceEntry
637 return nil
638}
639
640//creates a new ONU device or returns the existing
641func (dh *DeviceHandler) Add_OnuDeviceEntry(ctx context.Context) error {
642 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
643
644 deviceEntry := dh.GetOnuDeviceEntry()
645 if deviceEntry == nil {
646 /* costum_me_map in python code seems always to be None,
647 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
648 /* also no 'clock' argument - usage open ...*/
649 /* and no alarm_db yet (oo.alarm_db) */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000650 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost, dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
651 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000652 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
653 //error treatment possible //TODO!!!
654 dh.SetOnuDeviceEntry(deviceEntry)
655 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
656 } else {
657 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
658 }
659 // might be updated with some error handling !!!
660 return nil
661}
662
663// doStateInit provides the device update to the core
664func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000665 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
666 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
667
668 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000669
670 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
671 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
672 }
673
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000674 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
675 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
676 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
677 // but I would not know why, and the go code anyway dows not work with the device directly anymore in the OnuDeviceEntry
678 // so let's just try to keep it simple ...
679 /*
680 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
681 if err != nil || device == nil {
682 //TODO: needs to handle error scenarios
683 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
684 return errors.New("Voltha Device not found")
685 }
686 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000687
688 dh.GetOnuDeviceEntry().Start(context.TODO())
689 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
690 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
691 }
692
693 /* this might be a good time for Omci Verify message? */
694 verifyExec := make(chan bool)
695 omci_verify := NewOmciTestRequest(context.TODO(),
696 dh.device.Id, dh.GetOnuDeviceEntry().PDevOmciCC,
697 true, true) //eclusive and allowFailure (anyway not yet checked)
698 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
699
700 /* give the handler some time here to wait for the OMCi verification result
701 after Timeout start and try MibUpload FSM anyway
702 (to prevent stopping on just not supported OMCI verification from ONU) */
703 select {
704 case <-time.After(2 * time.Second):
705 logger.Warn("omci start-verification timed out (continue normal)")
706 case testresult := <-verifyExec:
707 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
708 }
709
710 /* In py code it looks earlier (on activate ..)
711 # Code to Run OMCI Test Action
712 kwargs_omci_test_action = {
713 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
714 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
715 }
716 serial_number = device.serial_number
717 self._test_request = OmciTestRequest(self.core_proxy,
718 self.omci_agent, self.device_id,
719 AniG, serial_number,
720 self.logical_device_id,
721 exclusive=False,
722 **kwargs_omci_test_action)
723 ...
724 # Start test requests after a brief pause
725 if not self._test_request_started:
726 self._test_request_started = True
727 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
728 reactor.callLater(tststart, self._test_request.start_collector)
729
730 */
731 /* which is then: in omci_test_request.py : */
732 /*
733 def start_collector(self, callback=None):
734 """
735 Start the collection loop for an adapter if the frequency > 0
736
737 :param callback: (callable) Function to call to collect PM data
738 """
739 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
740 if callback is None:
741 callback = self.perform_test_omci
742
743 if self.lc is None:
744 self.lc = LoopingCall(callback)
745
746 if self.default_freq > 0:
747 self.lc.start(interval=self.default_freq / 10)
748
749 def perform_test_omci(self):
750 """
751 Perform the initial test request
752 """
753 ani_g_entities = self._device.configuration.ani_g_entities
754 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
755 is not None else None
756 self._entity_id = ani_g_entities_ids[0]
757 self.logger.info('perform-test', entity_class=self._entity_class,
758 entity_id=self._entity_id)
759 try:
760 frame = MEFrame(self._entity_class, self._entity_id, []).test()
761 result = yield self._device.omci_cc.send(frame)
762 if not result.fields['omci_message'].fields['success_code']:
763 self.logger.info('Self-Test Submitted Successfully',
764 code=result.fields[
765 'omci_message'].fields['success_code'])
766 else:
767 raise TestFailure('Test Failure: {}'.format(
768 result.fields['omci_message'].fields['success_code']))
769 except TimeoutError as e:
770 self.deferred.errback(failure.Failure(e))
771
772 except Exception as e:
773 self.logger.exception('perform-test-Error', e=e,
774 class_id=self._entity_class,
775 entity_id=self._entity_id)
776 self.deferred.errback(failure.Failure(e))
777
778 */
779
780 // PM related heartbeat??? !!!TODO....
781 //self._heartbeat.enabled = True
782
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000783 //call MibUploadFSM - transition up to state "in_sync"
784 pMibUlFsm := dh.GetOnuDeviceEntry().pMibUploadFsm.pFsm
785 if pMibUlFsm != nil {
786 if pMibUlFsm.Is("disabled") {
787 if err := pMibUlFsm.Event("start"); err != nil {
788 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
789 return errors.New("Can't go to state starting")
790 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000791 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000792 //Determine ONU status and start/re-start MIB Synchronization tasks
793 //Determine if this ONU has ever synchronized
794 if true { //TODO: insert valid check
795 if err := pMibUlFsm.Event("load_mib_template"); err != nil {
796 logger.Errorw("MibSyncFsm: Can't go to state loading_mib_template", log.Fields{"err": err})
797 return errors.New("Can't go to state loading_mib_template")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000798 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000799 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000800 pMibUlFsm.Event("examine_mds")
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000801 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000802 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000803 // callbacks to be handled:
804 // Event("success")
805 // Event("timeout")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000806 // Event("mismatch")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000807 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000808 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000809 } else {
810 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
811 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000812 }
813 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000814 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000815 }
816 return nil
817}
818
819func (dh *DeviceHandler) update_interface(onuind *oop.OnuIndication) error {
820 logger.Debug("update_interface-started - not yet implemented")
821 return nil
822}
823
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000824func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
825 switch dev_Event {
826 case MibDatabaseSync:
827 {
828 logger.Infow("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
829 //initiate DevStateUpdate
830 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
831 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
832 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000833 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000834
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000835 unigMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.UniGClassID]
836 unigInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(unigMap)
837 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
838 if ok {
839 for _, mgmtEntityId := range unigInstKeys {
840 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
841 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
842 dh.addUniPort(mgmtEntityId, i, UniPPTP)
843 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000844 }
845 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000846 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000847 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000848 veipMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
849 veipInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(veipMap)
850 if ok {
851 for _, mgmtEntityId := range veipInstKeys {
852 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
853 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
854 dh.addUniPort(mgmtEntityId, i, UniVEIP)
855 i++
856 }
857 } else {
858 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
859 }
860 if i == 0 {
861 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
862 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000863
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000864 // Init Uni Ports to Admin locked state
865 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
866 // *** should generate UniLockStateDone event *****
867 if dh.pLockStateFsm == nil {
868 dh.createUniLockFsm(true, UniLockStateDone)
869 } else { //LockStateFSM already init
870 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
871 dh.runUniLockFsm(true)
872 }
873 }
874 case UniLockStateDone:
875 {
876 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
877 /* Mib download procedure -
878 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
879 */
880 pMibDlFsm := dh.GetOnuDeviceEntry().pMibDownloadFsm.pFsm
881 if pMibDlFsm != nil {
882 if pMibDlFsm.Is("disabled") {
883 if err := pMibDlFsm.Event("start"); err != nil {
884 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
885 // maybe try a FSM reset and then again ... - TODO!!!
886 } else {
887 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
888 // maybe use more specific states here for the specific download steps ...
889 if err := pMibDlFsm.Event("create_gal"); err != nil {
890 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
891 } else {
892 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
893 //Begin MIB data download (running autonomously)
894 }
895 }
896 } else {
897 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
898 // maybe try a FSM reset and then again ... - TODO!!!
899 }
900 /***** Mib download started */
901 } else {
902 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
903 }
904 }
905 case MibDownloadDone:
906 {
907 logger.Infow("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
908 //initiate DevStateUpdate
909 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
910 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
911 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
912 }
913 logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
914 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
915 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
916 log.Fields{"deviceID": dh.deviceID, "error": err})
917 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000918
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000919 // *** should generate UniUnlockStateDone event *****
920 if dh.pUnlockStateFsm == nil {
921 dh.createUniLockFsm(false, UniUnlockStateDone)
922 } else { //UnlockStateFSM already init
923 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
924 dh.runUniLockFsm(false)
925 }
926 }
927 case UniUnlockStateDone:
928 {
929 go dh.enableUniPortStateUpdate(dh.deviceID) //cmp python yield self.enable_ports()
930
931 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
932 raisedTs := time.Now().UnixNano()
933 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
934 }
935 default:
936 {
937 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
938 }
939 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000940}
941
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +0000942func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000943 // parameters are IntfId, OnuId, uniId
944 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
945 uint32(a_uniId))
946 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000947 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
948 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000949 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000950 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000951 if pUniPort == nil {
952 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
953 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000954 //store UniPort with the System-PortNumber key
955 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000956 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000957 if err := pUniPort.CreateVolthaPort(dh); err == nil {
958 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
959 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000960 }
961 }
962}
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000963
964// Enable listen on UniPortState changes and update core port state accordingly
965func (dh *DeviceHandler) enableUniPortStateUpdate(a_deviceID string) {
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000966 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
967 // but towards core only the first port active state is signalled
968 // with following remark:
969 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
970 // # load on the core
971
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000972 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000973
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000974 for uniNo, uniPort := range dh.uniEntityMap {
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000975 // only if this port is validated for operState transfer}
976 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
977 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
978 uniPort.SetOperState(vc.OperStatus_ACTIVE)
979 //maybe also use getter functions on uniPort - perhaps later ...
980 go dh.coreProxy.PortStateUpdate(context.TODO(), a_deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
981 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000982 }
983}
984
985// ONU_Active/Inactive announcement on system KAFKA bus
986// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
987func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
988 var de voltha.DeviceEvent
989 eventContext := make(map[string]string)
990 //Populating event context
991 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
992 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
993 if err != nil || parentDevice == nil {
994 logger.Errorw("Failed to fetch parent device for OnuEvent",
995 log.Fields{"parentId": dh.parentId, "err": err})
996 }
997 oltSerialNumber := parentDevice.SerialNumber
998
999 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1000 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1001 eventContext["serial-number"] = dh.device.SerialNumber
1002 eventContext["olt_serial_number"] = oltSerialNumber
1003 eventContext["device_id"] = a_deviceID
1004 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1005 logger.Debugw("prepare ONU_ACTIVATED event",
1006 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1007
1008 /* Populating device event body */
1009 de.Context = eventContext
1010 de.ResourceId = a_deviceID
1011 if a_OperState == voltha.OperStatus_ACTIVE {
1012 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1013 de.Description = fmt.Sprintf("%s Event - %s - %s",
1014 cEventObjectType, cOnuActivatedEvent, "Raised")
1015 } else {
1016 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1017 de.Description = fmt.Sprintf("%s Event - %s - %s",
1018 cEventObjectType, cOnuActivatedEvent, "Cleared")
1019 }
1020 /* Send event to KAFKA */
1021 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1022 logger.Warnw("could not send ONU_ACTIVATED event",
1023 log.Fields{"DeviceId": a_deviceID, "error": err})
1024 }
1025 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1026 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1027}
1028
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001029// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1030func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1031 chLSFsm := make(chan Message, 2048)
1032 var sFsmName string
1033 if aAdminState == true {
1034 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1035 sFsmName = "LockStateFSM"
1036 } else {
1037 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1038 sFsmName = "UnLockStateFSM"
1039 }
1040 pLSFsm := NewLockStateFsm(dh.GetOnuDeviceEntry().PDevOmciCC, aAdminState, devEvent,
1041 sFsmName, dh.deviceID, chLSFsm)
1042 if pLSFsm != nil {
1043 if aAdminState == true {
1044 dh.pLockStateFsm = pLSFsm
1045 } else {
1046 dh.pUnlockStateFsm = pLSFsm
1047 }
1048 dh.runUniLockFsm(aAdminState)
1049 } else {
1050 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1051 }
1052}
1053
1054// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1055func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1056 /* Uni Port lock/unlock procedure -
1057 ***** should run via 'adminDone' state and generate the argument requested event *****
1058 */
1059 var pLSStatemachine *fsm.FSM
1060 if aAdminState == true {
1061 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1062 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1063 if (dh.pUnlockStateFsm != nil) &&
1064 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1065 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
1066 }
1067 } else {
1068 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1069 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1070 if (dh.pLockStateFsm != nil) &&
1071 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1072 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
1073 }
1074 }
1075 if pLSStatemachine != nil {
1076 if pLSStatemachine.Is("disabled") {
1077 if err := pLSStatemachine.Event("start"); err != nil {
1078 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1079 // maybe try a FSM reset and then again ... - TODO!!!
1080 } else {
1081 /***** LockStateFSM started */
1082 logger.Debugw("LockStateFSM started", log.Fields{
1083 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1084 }
1085 } else {
1086 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1087 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1088 // maybe try a FSM reset and then again ... - TODO!!!
1089 }
1090 } else {
1091 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1092 // maybe try a FSM reset and then again ... - TODO!!!
1093 }
1094}
1095
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001096/* *********************************************************** */
1097
1098func genMacFromOctets(a_octets [6]uint8) string {
1099 return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
1100 a_octets[5], a_octets[4], a_octets[3],
1101 a_octets[2], a_octets[1], a_octets[0])
1102}
1103
1104//copied from OLT Adapter: unify centrally ?
1105func macAddressToUint32Array(mac string) []uint32 {
1106 slist := strings.Split(mac, ":")
1107 result := make([]uint32, len(slist))
1108 var err error
1109 var tmp int64
1110 for index, val := range slist {
1111 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
1112 return []uint32{1, 2, 3, 4, 5, 6}
1113 }
1114 result[index] = uint32(tmp)
1115 }
1116 return result
1117}