blob: f27e3da73cf89ce967e3f0f3abce5f64ff62c122 [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"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000026 "sync"
27 "time"
28
29 "github.com/gogo/protobuf/proto"
30 "github.com/golang/protobuf/ptypes"
31 "github.com/looplab/fsm"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +000032 me "github.com/opencord/omci-lib-go/generated"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000033 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
mpagenkoaf801632020-07-03 10:00:42 +000034 "github.com/opencord/voltha-lib-go/v3/pkg/db"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000035 "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"
38 oop "github.com/opencord/voltha-protos/v3/go/openolt"
39 "github.com/opencord/voltha-protos/v3/go/voltha"
40)
41
42/*
43// Constants for number of retries and for timeout
44const (
45 MaxRetry = 10
46 MaxTimeOutInMs = 500
47)
48*/
49
Holger Hildebrandt24d51952020-05-04 14:03:42 +000050//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
51const (
52 pon = voltha.EventSubCategory_PON
53 olt = voltha.EventSubCategory_OLT
54 ont = voltha.EventSubCategory_ONT
55 onu = voltha.EventSubCategory_ONU
56 nni = voltha.EventSubCategory_NNI
57 service = voltha.EventCategory_SERVICE
58 security = voltha.EventCategory_SECURITY
59 equipment = voltha.EventCategory_EQUIPMENT
60 processing = voltha.EventCategory_PROCESSING
61 environment = voltha.EventCategory_ENVIRONMENT
62 communication = voltha.EventCategory_COMMUNICATION
63)
64
65const (
66 cEventObjectType = "ONU"
67)
68const (
69 cOnuActivatedEvent = "ONU_ACTIVATED"
70)
71
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000072//DeviceHandler will interact with the ONU ? device.
73type DeviceHandler struct {
74 deviceID string
75 DeviceType string
76 adminState string
77 device *voltha.Device
78 logicalDeviceID string
79 ProxyAddressID string
80 ProxyAddressType string
Holger Hildebrandt24d51952020-05-04 14:03:42 +000081 parentId string
82 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000083
Holger Hildebrandtc54939a2020-06-17 08:14:27 +000084 coreProxy adapterif.CoreProxy
85 AdapterProxy adapterif.AdapterProxy
86 EventProxy adapterif.EventProxy
87
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000088 pOpenOnuAc *OpenONUAC
89 pDeviceStateFsm *fsm.FSM
90 pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +000091 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000092 pOnuOmciDevice *OnuDeviceEntry
mpagenkoaf801632020-07-03 10:00:42 +000093 pOnuTP *OnuUniTechProf
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000094 exitChannel chan int
95 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +000096 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +000097 deviceReason string
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000098 pLockStateFsm *LockStateFsm
99 pUnlockStateFsm *LockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000100
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000101 //flowMgr *OpenOltFlowMgr
102 //eventMgr *OpenOltEventMgr
103 //resourceMgr *rsrcMgr.OpenOltResourceMgr
104
105 //discOnus sync.Map
106 //onus sync.Map
107 //portStats *OpenOltStatisticsMgr
108 //metrics *pmmetrics.PmMetrics
109 stopCollector chan bool
110 stopHeartbeatCheck chan bool
111 activePorts sync.Map
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000112 uniEntityMap map[uint32]*OnuUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000113}
114
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000115//NewDeviceHandler creates a new device handler
116func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *DeviceHandler {
117 var dh DeviceHandler
118 dh.coreProxy = cp
119 dh.AdapterProxy = ap
120 dh.EventProxy = ep
121 cloned := (proto.Clone(device)).(*voltha.Device)
122 dh.deviceID = cloned.Id
123 dh.DeviceType = cloned.Type
124 dh.adminState = "up"
125 dh.device = cloned
126 dh.pOpenOnuAc = adapter
127 dh.exitChannel = make(chan int, 1)
128 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000129 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000130 dh.stopCollector = make(chan bool, 2)
131 dh.stopHeartbeatCheck = make(chan bool, 2)
132 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
133 dh.activePorts = sync.Map{}
134 //TODO initialize the support classes.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000135 dh.uniEntityMap = make(map[uint32]*OnuUniPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000136
137 // Device related state machine
138 dh.pDeviceStateFsm = fsm.NewFSM(
139 "null",
140 fsm.Events{
141 {Name: "DeviceInit", Src: []string{"null", "down"}, Dst: "init"},
142 {Name: "GrpcConnected", Src: []string{"init"}, Dst: "connected"},
143 {Name: "GrpcDisconnected", Src: []string{"connected", "down"}, Dst: "init"},
144 {Name: "DeviceUpInd", Src: []string{"connected", "down"}, Dst: "up"},
145 {Name: "DeviceDownInd", Src: []string{"up"}, Dst: "down"},
146 },
147 fsm.Callbacks{
148 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
149 "before_DeviceInit": func(e *fsm.Event) { dh.doStateInit(e) },
150 "after_DeviceInit": func(e *fsm.Event) { dh.postInit(e) },
151 "before_GrpcConnected": func(e *fsm.Event) { dh.doStateConnected(e) },
152 "before_GrpcDisconnected": func(e *fsm.Event) { dh.doStateInit(e) },
153 "after_GrpcDisconnected": func(e *fsm.Event) { dh.postInit(e) },
154 "before_DeviceUpInd": func(e *fsm.Event) { dh.doStateUp(e) },
155 "before_DeviceDownInd": func(e *fsm.Event) { dh.doStateDown(e) },
156 },
157 )
mpagenkoaf801632020-07-03 10:00:42 +0000158
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000159 return &dh
160}
161
162// start save the device to the data model
163func (dh *DeviceHandler) Start(ctx context.Context) {
164 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "deviceId": dh.deviceID})
165 // Add the initial device to the local model
166 logger.Debug("device-handler-started")
167}
168
169// stop stops the device dh. Not much to do for now
170func (dh *DeviceHandler) stop(ctx context.Context) {
171 logger.Debug("stopping-device-handler")
172 dh.exitChannel <- 1
173}
174
175// ##########################################################################################
176// DeviceHandler methods that implement the adapters interface requests ##### begin #########
177
178//AdoptDevice adopts the OLT device
179func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
180 logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
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 if dh.pDeviceStateFsm.Is("null") {
184 if err := dh.pDeviceStateFsm.Event("DeviceInit"); err != nil {
185 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
186 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000187 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000188 } else {
189 logger.Debug("AdoptDevice: Agent/device init already done")
190 }
191
192 /*
193 // Now, set the initial PM configuration for that device
194 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
195 logger.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
196 }
197
198 go startCollector(dh)
199 go startHeartbeatCheck(dh)
200 */
201}
202
203//ProcessInterAdapterMessage sends the proxied messages to the target device
204// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
205// is meant, and then send the unmarshalled omci message to this onu
206func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
207 msgID := msg.Header.Id
208 msgType := msg.Header.Type
209 fromTopic := msg.Header.FromTopic
210 toTopic := msg.Header.ToTopic
211 toDeviceID := msg.Header.ToDeviceId
212 proxyDeviceID := msg.Header.ProxyDeviceId
213 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
214 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
215
216 switch msgType {
217 case ic.InterAdapterMessageType_OMCI_REQUEST:
218 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000219 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000220 omciMsg := &ic.InterAdapterOmciMessage{}
221 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000222 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
223 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000224 return err
225 }
226
227 //assuming omci message content is hex coded!
228 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000229 logger.Debugw("inter-adapter-recv-omci", log.Fields{
230 "deviceID": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000231 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000232 pDevEntry := dh.GetOnuDeviceEntry(true)
233 if pDevEntry != nil {
234 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
235 } else {
236 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
237 return errors.New("No valid OnuDevice")
238 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000239 }
240 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
241 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000242 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000243 onu_indication := &oop.OnuIndication{}
244 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000245 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
246 "deviceID": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000247 return err
248 }
249
250 onu_operstate := onu_indication.GetOperState()
251 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
252 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
253 "SNR": onu_indication.GetSerialNumber()})
254
mpagenko3af1f032020-06-10 08:53:41 +0000255 //interface related functions might be error checked ....
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000256 if onu_operstate == "up" {
257 dh.create_interface(onu_indication)
258 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
mpagenko3af1f032020-06-10 08:53:41 +0000259 dh.updateInterface(onu_indication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000260 } else {
261 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
262 return errors.New("InvalidOperState")
263 }
264 }
mpagenkoaf801632020-07-03 10:00:42 +0000265 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
266 {
267 if dh.pOnuTP == nil {
268 //should normally not happen ...
269 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
270 log.Fields{"deviceID": dh.deviceID})
271 return errors.New("TechProfile DLMsg request while onuTechProf instance not setup")
272 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000273
mpagenkoaf801632020-07-03 10:00:42 +0000274 msgBody := msg.GetBody()
275 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
276 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
277 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
278 "deviceID": dh.deviceID, "error": err})
279 return err
280 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000281
mpagenkoaf801632020-07-03 10:00:42 +0000282 // we have to lock access to TechProfile processing based on different messageType calls or
283 // even to fast subsequent calls of the same messageType
284 dh.pOnuTP.lockTpProcMutex()
285 // lock hangs as long as below decoupled or other related TechProfile processing is active
286 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify == true {
287 // if there has been some change for some uni TechProfilePath
288 //in order to allow concurrent calls to other dh instances we do not wait for execution here
289 //but doing so we can not indicate problems to the caller (who does what with that then?)
290 //by now we just assume straightforward successful execution
291 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
292 // possible problems to the caller later autonomously
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000293
mpagenko3dbcdd22020-07-22 07:38:45 +0000294 // deadline context to ensure completion of background routines waited for
295 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
296 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
297 dctx, cancel := context.WithDeadline(context.Background(), deadline)
298
mpagenkoaf801632020-07-03 10:00:42 +0000299 var wg sync.WaitGroup
300 wg.Add(2) // for the 2 go routines to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000301 // attention: deadline completion check and wg.Done is to be done in both routines
302 go dh.pOnuTP.configureUniTp(dctx, techProfMsg.UniId, techProfMsg.Path, &wg)
303 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000304 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +0000305 go dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
mpagenkoaf801632020-07-03 10:00:42 +0000306 } else {
307 dh.pOnuTP.unlockTpProcMutex()
308 }
309 }
310 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
311 {
312 if dh.pOnuTP == nil {
313 //should normally not happen ...
314 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
315 log.Fields{"deviceID": dh.deviceID})
316 return errors.New("TechProfile DelGem request while onuTechProf instance not setup")
317 }
318
319 msgBody := msg.GetBody()
320 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
321 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
322 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
323 "deviceID": dh.deviceID, "error": err})
324 return err
325 }
326
327 //compare TECH_PROFILE_DOWNLOAD_REQUEST
328 dh.pOnuTP.lockTpProcMutex()
mpagenko3dbcdd22020-07-22 07:38:45 +0000329
330 // deadline context to ensure completion of background routines waited for
331 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
332 dctx, cancel := context.WithDeadline(context.Background(), deadline)
333
mpagenkoaf801632020-07-03 10:00:42 +0000334 var wg sync.WaitGroup
335 wg.Add(1) // for the 1 go routine to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000336 go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000337 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
338 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +0000339 go dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
mpagenkoaf801632020-07-03 10:00:42 +0000340 }
341 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
342 {
343 if dh.pOnuTP == nil {
344 //should normally not happen ...
345 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
346 log.Fields{"deviceID": dh.deviceID})
347 return errors.New("TechProfile DelTcont request while onuTechProf instance not setup")
348 }
349
350 msgBody := msg.GetBody()
351 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
352 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
353 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
354 "deviceID": dh.deviceID, "error": err})
355 return err
356 }
357
358 //compare TECH_PROFILE_DOWNLOAD_REQUEST
359 dh.pOnuTP.lockTpProcMutex()
360 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify == true {
mpagenko3dbcdd22020-07-22 07:38:45 +0000361 // deadline context to ensure completion of background routines waited for
362 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
363 dctx, cancel := context.WithDeadline(context.Background(), deadline)
364
mpagenkoaf801632020-07-03 10:00:42 +0000365 var wg sync.WaitGroup
mpagenko3dbcdd22020-07-22 07:38:45 +0000366 wg.Add(2) // for the 2 go routines to finish
367 go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000368 cResourceTcont, delTcontMsg.AllocId, &wg)
369 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
mpagenko3dbcdd22020-07-22 07:38:45 +0000370 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000371 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +0000372 go dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
mpagenkoaf801632020-07-03 10:00:42 +0000373 } else {
374 dh.pOnuTP.unlockTpProcMutex()
375 }
376 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000377 default:
378 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000379 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
380 "deviceID": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000381 return errors.New("unimplemented")
382 }
383 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000384 return nil
385}
386
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000387//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000388// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
389// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300390func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000391 logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
392
mpagenko3af1f032020-06-10 08:53:41 +0000393 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
394 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
395 if dh.deviceReason != "omci-admin-lock" {
396 // disable UNI ports/ONU
397 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
398 // here the result of the processing is not checked (trusted in background) *****
399 if dh.pLockStateFsm == nil {
400 dh.createUniLockFsm(true, UniAdminStateDone)
401 } else { //LockStateFSM already init
402 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
403 dh.runUniLockFsm(true)
404 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300405
mpagenko3af1f032020-06-10 08:53:41 +0000406 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
407 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
408 }
409 dh.deviceReason = "omci-admin-lock"
410 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
411 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
412 voltha.OperStatus_UNKNOWN); err != nil {
413 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
414 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300415 }
416}
417
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000418//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000419// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
420// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300421func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000422 logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000423
424 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300425 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
426 voltha.OperStatus_ACTIVE); err != nil {
427 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
428 }
429
mpagenko3af1f032020-06-10 08:53:41 +0000430 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000431 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
ozgecanetsiafce57b12020-05-25 14:39:35 +0300432 logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
433 }
mpagenko3af1f032020-06-10 08:53:41 +0000434 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000435
436 // enable ONU/UNI ports
437 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
438 // here the result of the processing is not checked (trusted in background) *****
439 if dh.pUnlockStateFsm == nil {
440 dh.createUniLockFsm(false, UniAdminStateDone)
441 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000442 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000443 dh.runUniLockFsm(false)
444 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300445}
446
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000447// DeviceHandler methods that implement the adapters interface requests## end #########
448// #####################################################################################
449
450// ################ to be updated acc. needs of ONU Device ########################
451// DeviceHandler StateMachine related state transition methods ##### begin #########
452
453func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
454 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})
455}
456
457// doStateInit provides the device update to the core
458func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
459
460 logger.Debug("doStateInit-started")
461 var err error
462
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000463 // populate what we know. rest comes later after mib sync
464 dh.device.Root = false
465 dh.device.Vendor = "OpenONU"
466 dh.device.Model = "go"
467 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000468 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000469
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000470 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000471 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
472
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000473 dh.parentId = dh.device.ParentId
474 dh.ponPortNumber = dh.device.ParentPortNo
475
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000476 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
477 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
478 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
479 logger.Debugw("device-updated", log.Fields{"deviceID": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
480 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000481 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000482
483 /*
484 self._pon = PonPort.create(self, self._pon_port_number)
485 self._pon.add_peer(self.parent_id, self._pon_port_number)
486 self.logger.debug('adding-pon-port-to-agent',
487 type=self._pon.get_port().type,
488 admin_state=self._pon.get_port().admin_state,
489 oper_status=self._pon.get_port().oper_status,
490 )
491 */
492 logger.Debug("adding-pon-port")
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000493 var ponPortNo uint32 = 1
494 if dh.ponPortNumber != 0 {
495 ponPortNo = dh.ponPortNumber
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000496 }
497
498 pPonPort := &voltha.Port{
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000499 PortNo: ponPortNo,
500 Label: fmt.Sprintf("pon-%d", ponPortNo),
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000501 Type: voltha.Port_PON_ONU,
502 OperStatus: voltha.OperStatus_ACTIVE,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000503 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
504 PortNo: ponPortNo}}, // Peer port is parent's port number
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000505 }
506 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
507 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
508 e.Cancel(err)
509 return
510 }
511 logger.Debug("doStateInit-done")
512}
513
514// postInit setups the DeviceEntry for the conerned device
515func (dh *DeviceHandler) postInit(e *fsm.Event) {
516
517 logger.Debug("postInit-started")
518 var err error
519 /*
520 dh.Client = oop.NewOpenoltClient(dh.clientCon)
521 dh.pTransitionMap.Handle(ctx, GrpcConnected)
522 return nil
523 */
mpagenko3af1f032020-06-10 08:53:41 +0000524 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
525 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000526 e.Cancel(err)
527 return
528 }
529
530 /*
531 ############################################################################
532 # Setup Alarm handler
533 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
534 device.serial_number)
535 ############################################################################
536 # Setup PM configuration for this device
537 # Pass in ONU specific options
538 kwargs = {
539 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
540 'heartbeat': self.heartbeat,
541 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
542 }
543 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
544 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
545 self.logical_device_id, device.serial_number,
546 grouped=True, freq_override=False, **kwargs)
547 pm_config = self._pm_metrics.make_proto()
548 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
549 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
550 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
551
552 # Note, ONU ID and UNI intf set in add_uni_port method
553 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
554 ani_ports=[self._pon])
555
556 # Code to Run OMCI Test Action
557 kwargs_omci_test_action = {
558 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
559 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
560 }
561 serial_number = device.serial_number
562 self._test_request = OmciTestRequest(self.core_proxy,
563 self.omci_agent, self.device_id,
564 AniG, serial_number,
565 self.logical_device_id,
566 exclusive=False,
567 **kwargs_omci_test_action)
568
569 self.enabled = True
570 else:
571 self.logger.info('onu-already-activated')
572 */
573 logger.Debug("postInit-done")
574}
575
576// doStateConnected get the device info and update to voltha core
577// for comparison of the original method (not that easy to uncomment): compare here:
578// voltha-openolt-adapter/adaptercore/device_handler.go
579// -> this one obviously initiates all communication interfaces of the device ...?
580func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
581
582 logger.Debug("doStateConnected-started")
583 var err error
584 err = errors.New("Device FSM: function not implemented yet!")
585 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000586 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700587 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000588}
589
590// doStateUp handle the onu up indication and update to voltha core
591func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
592
593 logger.Debug("doStateUp-started")
594 var err error
595 err = errors.New("Device FSM: function not implemented yet!")
596 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000597 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700598 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000599
600 /*
601 // Synchronous call to update device state - this method is run in its own go routine
602 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
603 voltha.OperStatus_ACTIVE); err != nil {
604 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
605 return err
606 }
607 return nil
608 */
609}
610
611// doStateDown handle the onu down indication
612func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
613
614 logger.Debug("doStateDown-started")
615 var err error
616
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000617 device := dh.device
618 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000619 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000620 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000621 e.Cancel(err)
622 return
623 }
624
625 cloned := proto.Clone(device).(*voltha.Device)
626 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
627 /*
628 // Update the all ports state on that device to disable
629 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
630 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
631 return er
632 }
633
634 //Update the device oper state and connection status
635 cloned.OperStatus = voltha.OperStatus_UNKNOWN
636 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
637 dh.device = cloned
638
639 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
640 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
641 return er
642 }
643
644 //get the child device for the parent device
645 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
646 if err != nil {
647 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
648 return err
649 }
650 for _, onuDevice := range onuDevices.Items {
651
652 // Update onu state as down in onu adapter
653 onuInd := oop.OnuIndication{}
654 onuInd.OperState = "down"
655 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
656 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
657 if er != nil {
658 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
659 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
660 //Do not return here and continue to process other ONUs
661 }
662 }
663 // * Discovered ONUs entries need to be cleared , since after OLT
664 // is up, it starts sending discovery indications again* /
665 dh.discOnus = sync.Map{}
666 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
667 return nil
668 */
669 err = errors.New("Device FSM: function not implemented yet!")
670 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000671 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700672 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000673}
674
675// DeviceHandler StateMachine related state transition methods ##### end #########
676// #################################################################################
677
678// ###################################################
679// DeviceHandler utility methods ##### begin #########
680
mpagenko3af1f032020-06-10 08:53:41 +0000681//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
682func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
683 dh.lockDevice.RLock()
684 pOnuDeviceEntry := dh.pOnuOmciDevice
685 if aWait && pOnuDeviceEntry == nil {
686 //keep the read sema short to allow for subsequent write
687 dh.lockDevice.RUnlock()
688 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"deviceID": dh.deviceID})
689 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
690 // so it might be needed to wait here for that event with some timeout
691 select {
692 case <-time.After(60 * time.Second): //timer may be discussed ...
693 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"deviceID": dh.deviceID})
694 return nil
695 case <-dh.deviceEntrySet:
696 logger.Debugw("devicEntry ready now - continue", log.Fields{"deviceID": dh.deviceID})
697 // if written now, we can return the written value without sema
698 return dh.pOnuOmciDevice
699 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000700 }
mpagenko3af1f032020-06-10 08:53:41 +0000701 dh.lockDevice.RUnlock()
702 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000703}
704
mpagenko3af1f032020-06-10 08:53:41 +0000705//SetOnuDeviceEntry sets the ONU device entry within the handler
mpagenkoaf801632020-07-03 10:00:42 +0000706func (dh *DeviceHandler) SetOnuDeviceEntry(
707 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000708 dh.lockDevice.Lock()
709 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000710 dh.pOnuOmciDevice = apDeviceEntry
711 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000712 return nil
713}
714
mpagenko3af1f032020-06-10 08:53:41 +0000715//AddOnuDeviceEntry creates a new ONU device or returns the existing
716func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000717 logger.Debugw("adding-deviceEntry", log.Fields{"for deviceId": dh.deviceID})
718
mpagenko3af1f032020-06-10 08:53:41 +0000719 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000720 if deviceEntry == nil {
721 /* costum_me_map in python code seems always to be None,
722 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
723 /* also no 'clock' argument - usage open ...*/
724 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000725 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
726 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000727 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000728 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000729 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000730 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000731 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000732 // fire deviceEntry ready event to spread to possibly waiting processing
733 dh.deviceEntrySet <- true
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000734 logger.Infow("onuDeviceEntry-added", log.Fields{"for deviceId": dh.deviceID})
735 } else {
736 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"for deviceId": dh.deviceID})
737 }
738 // might be updated with some error handling !!!
739 return nil
740}
741
742// doStateInit provides the device update to the core
743func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000744 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
745 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
746
747 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000748
mpagenko3af1f032020-06-10 08:53:41 +0000749 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
750 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000751 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
752 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000753 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
754 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
755 // in python code it looks as the started onu_omci_device might have been updated with some new instance state of the core device
mpagenkoaf801632020-07-03 10:00:42 +0000756 // but I would not know why, and the go code anyway does not work with the device directly anymore in the OnuDeviceEntry
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000757 // so let's just try to keep it simple ...
758 /*
759 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
760 if err != nil || device == nil {
761 //TODO: needs to handle error scenarios
762 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
763 return errors.New("Voltha Device not found")
764 }
765 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000766
mpagenko3af1f032020-06-10 08:53:41 +0000767 pDevEntry := dh.GetOnuDeviceEntry(true)
768 if pDevEntry != nil {
769 pDevEntry.Start(context.TODO())
770 } else {
771 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
772 return errors.New("No valid OnuDevice")
773 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000774 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
775 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"deviceID": dh.deviceID, "error": err})
776 }
mpagenko3af1f032020-06-10 08:53:41 +0000777 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000778
779 /* this might be a good time for Omci Verify message? */
780 verifyExec := make(chan bool)
781 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000782 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000783 true, true) //eclusive and allowFailure (anyway not yet checked)
784 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
785
786 /* give the handler some time here to wait for the OMCi verification result
787 after Timeout start and try MibUpload FSM anyway
788 (to prevent stopping on just not supported OMCI verification from ONU) */
789 select {
790 case <-time.After(2 * time.Second):
791 logger.Warn("omci start-verification timed out (continue normal)")
792 case testresult := <-verifyExec:
793 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
794 }
795
796 /* In py code it looks earlier (on activate ..)
797 # Code to Run OMCI Test Action
798 kwargs_omci_test_action = {
799 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
800 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
801 }
802 serial_number = device.serial_number
803 self._test_request = OmciTestRequest(self.core_proxy,
804 self.omci_agent, self.device_id,
805 AniG, serial_number,
806 self.logical_device_id,
807 exclusive=False,
808 **kwargs_omci_test_action)
809 ...
810 # Start test requests after a brief pause
811 if not self._test_request_started:
812 self._test_request_started = True
813 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
814 reactor.callLater(tststart, self._test_request.start_collector)
815
816 */
817 /* which is then: in omci_test_request.py : */
818 /*
819 def start_collector(self, callback=None):
820 """
821 Start the collection loop for an adapter if the frequency > 0
822
823 :param callback: (callable) Function to call to collect PM data
824 """
825 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
826 if callback is None:
827 callback = self.perform_test_omci
828
829 if self.lc is None:
830 self.lc = LoopingCall(callback)
831
832 if self.default_freq > 0:
833 self.lc.start(interval=self.default_freq / 10)
834
835 def perform_test_omci(self):
836 """
837 Perform the initial test request
838 """
839 ani_g_entities = self._device.configuration.ani_g_entities
840 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
841 is not None else None
842 self._entity_id = ani_g_entities_ids[0]
843 self.logger.info('perform-test', entity_class=self._entity_class,
844 entity_id=self._entity_id)
845 try:
846 frame = MEFrame(self._entity_class, self._entity_id, []).test()
847 result = yield self._device.omci_cc.send(frame)
848 if not result.fields['omci_message'].fields['success_code']:
849 self.logger.info('Self-Test Submitted Successfully',
850 code=result.fields[
851 'omci_message'].fields['success_code'])
852 else:
853 raise TestFailure('Test Failure: {}'.format(
854 result.fields['omci_message'].fields['success_code']))
855 except TimeoutError as e:
856 self.deferred.errback(failure.Failure(e))
857
858 except Exception as e:
859 self.logger.exception('perform-test-Error', e=e,
860 class_id=self._entity_class,
861 entity_id=self._entity_id)
862 self.deferred.errback(failure.Failure(e))
863
864 */
865
866 // PM related heartbeat??? !!!TODO....
867 //self._heartbeat.enabled = True
868
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000869 //call MibUploadFSM - transition up to state "in_sync"
mpagenko3af1f032020-06-10 08:53:41 +0000870 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000871 if pMibUlFsm != nil {
872 if pMibUlFsm.Is("disabled") {
873 if err := pMibUlFsm.Event("start"); err != nil {
874 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
875 return errors.New("Can't go to state starting")
876 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000877 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000878 //Determine ONU status and start/re-start MIB Synchronization tasks
879 //Determine if this ONU has ever synchronized
880 if true { //TODO: insert valid check
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000881 if err := pMibUlFsm.Event("reset_mib"); err != nil {
882 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
883 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000884 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000885 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000886 pMibUlFsm.Event("examine_mds")
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000887 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000888 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000889 // callbacks to be handled:
890 // Event("success")
891 // Event("timeout")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000892 // Event("mismatch")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000893 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000894 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000895 } else {
896 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
897 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000898 }
899 } else {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000900 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000901 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000902 }
903 return nil
904}
905
mpagenko3af1f032020-06-10 08:53:41 +0000906func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
907 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
908 if dh.deviceReason != "stopping-openomci" {
909 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"deviceID": dh.deviceID})
910 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
911 pDevEntry := dh.GetOnuDeviceEntry(false)
912 if pDevEntry == nil {
913 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
914 return errors.New("No valid OnuDevice")
915 }
916
917 switch dh.deviceReason {
918 case "starting-openomci":
919 { //MIBSync FSM may run
920 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
921 if pMibUlFsm != nil {
922 pMibUlFsm.Event("stop") //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
923 }
924 }
925 case "discovery-mibsync-complete":
926 { //MibDownload may run
927 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
928 if pMibDlFsm != nil {
929 pMibDlFsm.Event("reset")
930 }
931 }
932 default:
mpagenko3dbcdd22020-07-22 07:38:45 +0000933 {
934 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +0000935 if dh.pUnlockStateFsm != nil {
936 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
937 }
938 if dh.pLockStateFsm != nil {
939 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
940 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000941 //techProfile related PonAniConfigFsm FSM may be active
942 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
943 if dh.pOnuTP.pAniConfigFsm != nil {
944 dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event("reset")
945 }
mpagenko3af1f032020-06-10 08:53:41 +0000946 }
947 //TODO!!! care about PM/Alarm processing once started
948 }
949 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
950 // (mainly the still seperate 'Event states')
951 // so it is questionable, how this is resolved after some possible re-enable
952 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
953
954 //stop/remove(?) the device entry
955 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
956
957 //TODO!!! remove existing traffic profiles
958 /* from py code, if TP's exist, remove them - not yet implemented
959 self._tp = dict()
960 # Let TP download happen again
961 for uni_id in self._tp_service_specific_task:
962 self._tp_service_specific_task[uni_id].clear()
963 for uni_id in self._tech_profile_download_done:
964 self._tech_profile_download_done[uni_id].clear()
965 */
966
967 dh.disableUniPortStateUpdate()
968
969 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
970 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
971 log.Fields{"deviceID": dh.deviceID, "error": err})
972 // abort: system behavior is just unstable ...
973 return err
974 }
975 dh.deviceReason = "stopping-openomci"
976
977 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
978 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
979 logger.Errorw("error-updating-device-state unreachable-discovered",
980 log.Fields{"deviceID": dh.deviceID, "error": err})
981 // abort: system behavior is just unstable ...
982 return err
983 }
984 } else {
985 logger.Debugw("updateInterface - device already stopped", log.Fields{"deviceID": dh.deviceID})
986 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000987 return nil
988}
989
mpagenko3af1f032020-06-10 08:53:41 +0000990//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000991func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
992 switch dev_Event {
993 case MibDatabaseSync:
994 {
mpagenko3dbcdd22020-07-22 07:38:45 +0000995 logger.Debugw("MibInSync event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000996 //initiate DevStateUpdate
997 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
998 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
999 "deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001000 } else {
1001 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001002 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001003 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001004 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001005
mpagenko3af1f032020-06-10 08:53:41 +00001006 pDevEntry := dh.GetOnuDeviceEntry(false)
1007 unigMap, ok := pDevEntry.pOnuDB.meDb[me.UniGClassID]
1008 unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(unigMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001009 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
1010 if ok {
1011 for _, mgmtEntityId := range unigInstKeys {
1012 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1013 "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
1014 dh.addUniPort(mgmtEntityId, i, UniPPTP)
1015 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001016 }
1017 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001018 logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001019 }
mpagenko3af1f032020-06-10 08:53:41 +00001020 veipMap, ok := pDevEntry.pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
1021 veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(veipMap)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001022 if ok {
1023 for _, mgmtEntityId := range veipInstKeys {
1024 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1025 "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
1026 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1027 i++
1028 }
1029 } else {
1030 logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
1031 }
1032 if i == 0 {
1033 logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
1034 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001035
mpagenko3af1f032020-06-10 08:53:41 +00001036 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1037 * left the code here as comment in case such processing should prove needed unexpectedly
1038 // Init Uni Ports to Admin locked state
1039 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1040 // *** should generate UniLockStateDone event *****
1041 if dh.pLockStateFsm == nil {
1042 dh.createUniLockFsm(true, UniLockStateDone)
1043 } else { //LockStateFSM already init
1044 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1045 dh.runUniLockFsm(true)
1046 }
1047 }
1048 case UniLockStateDone:
1049 {
1050 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
1051 * lockState processing commented out
1052 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001053 /* Mib download procedure -
1054 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1055 */
mpagenko3af1f032020-06-10 08:53:41 +00001056 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001057 if pMibDlFsm != nil {
1058 if pMibDlFsm.Is("disabled") {
1059 if err := pMibDlFsm.Event("start"); err != nil {
1060 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1061 // maybe try a FSM reset and then again ... - TODO!!!
1062 } else {
1063 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1064 // maybe use more specific states here for the specific download steps ...
1065 if err := pMibDlFsm.Event("create_gal"); err != nil {
1066 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1067 } else {
1068 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1069 //Begin MIB data download (running autonomously)
1070 }
1071 }
1072 } else {
1073 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1074 // maybe try a FSM reset and then again ... - TODO!!!
1075 }
1076 /***** Mib download started */
1077 } else {
1078 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1079 }
1080 }
1081 case MibDownloadDone:
1082 {
mpagenko3dbcdd22020-07-22 07:38:45 +00001083 logger.Debugw("MibDownloadDone event received", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001084 //initiate DevStateUpdate
1085 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1086 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1087 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001088 } else {
1089 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001090 }
mpagenko3af1f032020-06-10 08:53:41 +00001091
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001092 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1093 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1094 log.Fields{"deviceID": dh.deviceID, "error": err})
mpagenko3dbcdd22020-07-22 07:38:45 +00001095 } else {
1096 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001097 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001098 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001099 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001100 // *** should generate UniUnlockStateDone event *****
1101 if dh.pUnlockStateFsm == nil {
1102 dh.createUniLockFsm(false, UniUnlockStateDone)
1103 } else { //UnlockStateFSM already init
1104 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1105 dh.runUniLockFsm(false)
1106 }
1107 }
1108 case UniUnlockStateDone:
1109 {
mpagenko3af1f032020-06-10 08:53:41 +00001110 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001111
1112 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
1113 raisedTs := time.Now().UnixNano()
1114 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1115 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001116 case OmciAniConfigDone:
1117 {
1118 logger.Debugw("OmciAniConfigDone event received", log.Fields{"deviceID": dh.deviceID})
1119 //TODO!: it might be needed to check some 'cached' pending flow configuration (vlan setting)
1120 // - to consider with outstanding flow implementation
1121 // attention: the device reason update is done based on ONU-UNI-Port related activity
1122 // - which may cause some inconsistency
1123 if dh.deviceReason != "tech-profile-config-download-success" {
1124 // which may be the case from some previous actvity on another UNI Port of the ONU
1125 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1126 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1127 log.Fields{"deviceID": dh.deviceID, "error": err})
1128 } else {
1129 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1130 log.Fields{"deviceID": dh.deviceID})
1131 }
1132 //set internal state anyway - as it was done
1133 dh.deviceReason = "tech-profile-config-download-success"
1134 }
1135 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001136 default:
1137 {
1138 logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
1139 }
1140 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001141}
1142
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001143func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001144 // parameters are IntfId, OnuId, uniId
1145 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1146 uint32(a_uniId))
1147 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001148 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1149 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001150 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001151 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001152 if pUniPort == nil {
1153 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1154 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001155 //store UniPort with the System-PortNumber key
1156 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001157 // create announce the UniPort to the core as VOLTHA Port object
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001158 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1159 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1160 } //error logging already within UniPort method
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001161 }
1162 }
1163}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001164
mpagenko3af1f032020-06-10 08:53:41 +00001165// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1166func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001167 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1168 // but towards core only the first port active state is signalled
1169 // with following remark:
1170 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1171 // # load on the core
1172
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001173 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001174
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001175 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001176 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001177 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1178 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1179 uniPort.SetOperState(vc.OperStatus_ACTIVE)
1180 //maybe also use getter functions on uniPort - perhaps later ...
mpagenko3af1f032020-06-10 08:53:41 +00001181 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1182 }
1183 }
1184}
1185
1186// Disable UniPortState and update core port state accordingly
1187func (dh *DeviceHandler) disableUniPortStateUpdate() {
1188 // compare enableUniPortStateUpdate() above
1189 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1190 for uniNo, uniPort := range dh.uniEntityMap {
1191 // only if this port is validated for operState transfer
1192 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1193 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1194 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1195 //maybe also use getter functions on uniPort - perhaps later ...
1196 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001197 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001198 }
1199}
1200
1201// ONU_Active/Inactive announcement on system KAFKA bus
1202// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1203func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1204 var de voltha.DeviceEvent
1205 eventContext := make(map[string]string)
1206 //Populating event context
1207 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1208 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1209 if err != nil || parentDevice == nil {
1210 logger.Errorw("Failed to fetch parent device for OnuEvent",
1211 log.Fields{"parentId": dh.parentId, "err": err})
1212 }
1213 oltSerialNumber := parentDevice.SerialNumber
1214
1215 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1216 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1217 eventContext["serial-number"] = dh.device.SerialNumber
1218 eventContext["olt_serial_number"] = oltSerialNumber
1219 eventContext["device_id"] = a_deviceID
1220 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1221 logger.Debugw("prepare ONU_ACTIVATED event",
1222 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1223
1224 /* Populating device event body */
1225 de.Context = eventContext
1226 de.ResourceId = a_deviceID
1227 if a_OperState == voltha.OperStatus_ACTIVE {
1228 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1229 de.Description = fmt.Sprintf("%s Event - %s - %s",
1230 cEventObjectType, cOnuActivatedEvent, "Raised")
1231 } else {
1232 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1233 de.Description = fmt.Sprintf("%s Event - %s - %s",
1234 cEventObjectType, cOnuActivatedEvent, "Cleared")
1235 }
1236 /* Send event to KAFKA */
1237 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1238 logger.Warnw("could not send ONU_ACTIVATED event",
1239 log.Fields{"DeviceId": a_deviceID, "error": err})
1240 }
1241 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
1242 log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
1243}
1244
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001245// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1246func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1247 chLSFsm := make(chan Message, 2048)
1248 var sFsmName string
1249 if aAdminState == true {
1250 logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
1251 sFsmName = "LockStateFSM"
1252 } else {
1253 logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
1254 sFsmName = "UnLockStateFSM"
1255 }
mpagenko3af1f032020-06-10 08:53:41 +00001256
1257 pDevEntry := dh.GetOnuDeviceEntry(true)
1258 if pDevEntry == nil {
1259 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"deviceID": dh.deviceID})
1260 return
1261 }
1262 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001263 sFsmName, dh.deviceID, chLSFsm)
1264 if pLSFsm != nil {
1265 if aAdminState == true {
1266 dh.pLockStateFsm = pLSFsm
1267 } else {
1268 dh.pUnlockStateFsm = pLSFsm
1269 }
1270 dh.runUniLockFsm(aAdminState)
1271 } else {
1272 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
1273 }
1274}
1275
1276// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1277func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1278 /* Uni Port lock/unlock procedure -
1279 ***** should run via 'adminDone' state and generate the argument requested event *****
1280 */
1281 var pLSStatemachine *fsm.FSM
1282 if aAdminState == true {
1283 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1284 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1285 if (dh.pUnlockStateFsm != nil) &&
1286 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1287 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
1288 }
1289 } else {
1290 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1291 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1292 if (dh.pLockStateFsm != nil) &&
1293 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
1294 dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
1295 }
1296 }
1297 if pLSStatemachine != nil {
1298 if pLSStatemachine.Is("disabled") {
1299 if err := pLSStatemachine.Event("start"); err != nil {
1300 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1301 // maybe try a FSM reset and then again ... - TODO!!!
1302 } else {
1303 /***** LockStateFSM started */
1304 logger.Debugw("LockStateFSM started", log.Fields{
1305 "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1306 }
1307 } else {
1308 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
1309 "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
1310 // maybe try a FSM reset and then again ... - TODO!!!
1311 }
1312 } else {
1313 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
1314 // maybe try a FSM reset and then again ... - TODO!!!
1315 }
1316}
1317
mpagenkoaf801632020-07-03 10:00:42 +00001318//SetBackend provides a DB backend for the specified path on the existing KV client
1319func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1320 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1321 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
1322 "BasePathKvStore": aBasePathKvStore, "deviceId": dh.deviceID})
1323 kvbackend := &db.Backend{
1324 Client: dh.pOpenOnuAc.kvClient,
1325 StoreType: dh.pOpenOnuAc.KVStoreType,
1326 /* address config update acc. to [VOL-2736] */
1327 Address: addr,
1328 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1329 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001330
mpagenkoaf801632020-07-03 10:00:42 +00001331 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001332}