blob: 93dbb6c51639cb9932df5a2265c8bd130e5c4222 [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
mpagenko1cc3cb42020-07-27 15:24:38 +000050const (
51 // events of Device FSM
52 devEvDeviceInit = "devEvDeviceInit"
53 devEvGrpcConnected = "devEvGrpcConnected"
54 devEvGrpcDisconnected = "devEvGrpcDisconnected"
55 devEvDeviceUpInd = "devEvDeviceUpInd"
56 devEvDeviceDownInd = "devEvDeviceDownInd"
57)
58const (
59 // states of Device FSM
60 devStNull = "devStNull"
61 devStDown = "devStDown"
62 devStInit = "devStInit"
63 devStConnected = "devStConnected"
64 devStUp = "devStUp"
65)
66
Holger Hildebrandt24d51952020-05-04 14:03:42 +000067//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
68const (
69 pon = voltha.EventSubCategory_PON
70 olt = voltha.EventSubCategory_OLT
71 ont = voltha.EventSubCategory_ONT
72 onu = voltha.EventSubCategory_ONU
73 nni = voltha.EventSubCategory_NNI
74 service = voltha.EventCategory_SERVICE
75 security = voltha.EventCategory_SECURITY
76 equipment = voltha.EventCategory_EQUIPMENT
77 processing = voltha.EventCategory_PROCESSING
78 environment = voltha.EventCategory_ENVIRONMENT
79 communication = voltha.EventCategory_COMMUNICATION
80)
81
82const (
83 cEventObjectType = "ONU"
84)
85const (
86 cOnuActivatedEvent = "ONU_ACTIVATED"
87)
88
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000089//DeviceHandler will interact with the ONU ? device.
90type DeviceHandler struct {
91 deviceID string
92 DeviceType string
93 adminState string
94 device *voltha.Device
95 logicalDeviceID string
96 ProxyAddressID string
97 ProxyAddressType string
Holger Hildebrandt24d51952020-05-04 14:03:42 +000098 parentId string
99 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000100
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000101 coreProxy adapterif.CoreProxy
102 AdapterProxy adapterif.AdapterProxy
103 EventProxy adapterif.EventProxy
104
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000105 pOpenOnuAc *OpenONUAC
106 pDeviceStateFsm *fsm.FSM
107 pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +0000108 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000109 pOnuOmciDevice *OnuDeviceEntry
mpagenkoaf801632020-07-03 10:00:42 +0000110 pOnuTP *OnuUniTechProf
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000111 exitChannel chan int
112 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000113 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +0000114 deviceReason string
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000115 pLockStateFsm *LockStateFsm
116 pUnlockStateFsm *LockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000117
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000118 //flowMgr *OpenOltFlowMgr
119 //eventMgr *OpenOltEventMgr
120 //resourceMgr *rsrcMgr.OpenOltResourceMgr
121
122 //discOnus sync.Map
123 //onus sync.Map
124 //portStats *OpenOltStatisticsMgr
125 //metrics *pmmetrics.PmMetrics
126 stopCollector chan bool
127 stopHeartbeatCheck chan bool
128 activePorts sync.Map
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000129 uniEntityMap map[uint32]*OnuUniPort
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000130 reconciling bool
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000131}
132
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000133//NewDeviceHandler creates a new device handler
134func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *DeviceHandler {
135 var dh DeviceHandler
136 dh.coreProxy = cp
137 dh.AdapterProxy = ap
138 dh.EventProxy = ep
139 cloned := (proto.Clone(device)).(*voltha.Device)
140 dh.deviceID = cloned.Id
141 dh.DeviceType = cloned.Type
142 dh.adminState = "up"
143 dh.device = cloned
144 dh.pOpenOnuAc = adapter
145 dh.exitChannel = make(chan int, 1)
146 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000147 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000148 dh.stopCollector = make(chan bool, 2)
149 dh.stopHeartbeatCheck = make(chan bool, 2)
150 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
151 dh.activePorts = sync.Map{}
152 //TODO initialize the support classes.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000153 dh.uniEntityMap = make(map[uint32]*OnuUniPort)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000154 dh.reconciling = false
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000155
156 // Device related state machine
157 dh.pDeviceStateFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000158 devStNull,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000159 fsm.Events{
mpagenko1cc3cb42020-07-27 15:24:38 +0000160 {Name: devEvDeviceInit, Src: []string{devStNull, devStDown}, Dst: devStInit},
161 {Name: devEvGrpcConnected, Src: []string{devStInit}, Dst: devStConnected},
162 {Name: devEvGrpcDisconnected, Src: []string{devStConnected, devStDown}, Dst: devStInit},
163 {Name: devEvDeviceUpInd, Src: []string{devStConnected, devStDown}, Dst: devStUp},
164 {Name: devEvDeviceDownInd, Src: []string{devStUp}, Dst: devStDown},
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000165 },
166 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000167 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
168 ("before_" + devEvDeviceInit): func(e *fsm.Event) { dh.doStateInit(e) },
169 ("after_" + devEvDeviceInit): func(e *fsm.Event) { dh.postInit(e) },
170 ("before_" + devEvGrpcConnected): func(e *fsm.Event) { dh.doStateConnected(e) },
171 ("before_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.doStateInit(e) },
172 ("after_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.postInit(e) },
173 ("before_" + devEvDeviceUpInd): func(e *fsm.Event) { dh.doStateUp(e) },
174 ("before_" + devEvDeviceDownInd): func(e *fsm.Event) { dh.doStateDown(e) },
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000175 },
176 )
mpagenkoaf801632020-07-03 10:00:42 +0000177
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000178 return &dh
179}
180
181// start save the device to the data model
182func (dh *DeviceHandler) Start(ctx context.Context) {
divyadesai4d299552020-08-18 07:13:49 +0000183 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000184 // Add the initial device to the local model
185 logger.Debug("device-handler-started")
186}
187
188// stop stops the device dh. Not much to do for now
189func (dh *DeviceHandler) stop(ctx context.Context) {
190 logger.Debug("stopping-device-handler")
191 dh.exitChannel <- 1
192}
193
194// ##########################################################################################
195// DeviceHandler methods that implement the adapters interface requests ##### begin #########
196
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000197//AdoptOrReconcileDevice adopts the OLT device
198func (dh *DeviceHandler) AdoptOrReconcileDevice(ctx context.Context, device *voltha.Device) {
199 logger.Debugw("Adopt_or_reconcile_device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000200
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000201 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
mpagenko1cc3cb42020-07-27 15:24:38 +0000202 if dh.pDeviceStateFsm.Is(devStNull) {
203 if err := dh.pDeviceStateFsm.Event(devEvDeviceInit); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000204 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
205 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000206 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000207 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000208 logger.Debugw("AdoptOrReconcileDevice: Agent/device init already done", log.Fields{"device-id": device.Id})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000209 }
210
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000211}
212
213//ProcessInterAdapterMessage sends the proxied messages to the target device
214// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
215// is meant, and then send the unmarshalled omci message to this onu
216func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
217 msgID := msg.Header.Id
218 msgType := msg.Header.Type
219 fromTopic := msg.Header.FromTopic
220 toTopic := msg.Header.ToTopic
221 toDeviceID := msg.Header.ToDeviceId
222 proxyDeviceID := msg.Header.ProxyDeviceId
223 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
224 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
225
226 switch msgType {
227 case ic.InterAdapterMessageType_OMCI_REQUEST:
228 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000229 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000230 omciMsg := &ic.InterAdapterOmciMessage{}
231 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000232 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000233 "device-id": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000234 return err
235 }
236
237 //assuming omci message content is hex coded!
238 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000239 logger.Debugw("inter-adapter-recv-omci", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000240 "device-id": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000241 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000242 pDevEntry := dh.GetOnuDeviceEntry(true)
243 if pDevEntry != nil {
244 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
245 } else {
divyadesai4d299552020-08-18 07:13:49 +0000246 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000247 return errors.New("No valid OnuDevice")
248 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000249 }
250 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
251 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000252 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000253 onu_indication := &oop.OnuIndication{}
254 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000255 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000256 "device-id": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000257 return err
258 }
259
260 onu_operstate := onu_indication.GetOperState()
261 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
262 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
263 "SNR": onu_indication.GetSerialNumber()})
264
mpagenko3af1f032020-06-10 08:53:41 +0000265 //interface related functions might be error checked ....
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000266 if onu_operstate == "up" {
267 dh.create_interface(onu_indication)
268 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
mpagenko3af1f032020-06-10 08:53:41 +0000269 dh.updateInterface(onu_indication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000270 } else {
271 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
272 return errors.New("InvalidOperState")
273 }
274 }
mpagenkoaf801632020-07-03 10:00:42 +0000275 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
276 {
277 if dh.pOnuTP == nil {
278 //should normally not happen ...
279 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000280 log.Fields{"device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000281 return errors.New("TechProfile DLMsg request while onuTechProf instance not setup")
282 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000283 if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
284 // I've seen cases for this request, where the device was already stopped
divyadesai4d299552020-08-18 07:13:49 +0000285 logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000286 return errors.New("device-unreachable")
287 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000288
mpagenkoaf801632020-07-03 10:00:42 +0000289 msgBody := msg.GetBody()
290 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
291 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
292 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000293 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000294 return err
295 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000296
mpagenkoaf801632020-07-03 10:00:42 +0000297 // we have to lock access to TechProfile processing based on different messageType calls or
298 // even to fast subsequent calls of the same messageType
299 dh.pOnuTP.lockTpProcMutex()
300 // lock hangs as long as below decoupled or other related TechProfile processing is active
301 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify == true {
302 // if there has been some change for some uni TechProfilePath
303 //in order to allow concurrent calls to other dh instances we do not wait for execution here
304 //but doing so we can not indicate problems to the caller (who does what with that then?)
305 //by now we just assume straightforward successful execution
306 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
307 // possible problems to the caller later autonomously
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000308
mpagenko3dbcdd22020-07-22 07:38:45 +0000309 // deadline context to ensure completion of background routines waited for
310 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
311 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
312 dctx, cancel := context.WithDeadline(context.Background(), deadline)
313
mpagenko1cc3cb42020-07-27 15:24:38 +0000314 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000315 var wg sync.WaitGroup
316 wg.Add(2) // for the 2 go routines to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000317 // attention: deadline completion check and wg.Done is to be done in both routines
318 go dh.pOnuTP.configureUniTp(dctx, techProfMsg.UniId, techProfMsg.Path, &wg)
319 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000320 //the wait.. function is responsible for tpProcMutex.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000321 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
mpagenko1cc3cb42020-07-27 15:24:38 +0000322 return err
mpagenkoaf801632020-07-03 10:00:42 +0000323 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000324 // no change, nothing really to do
325 dh.pOnuTP.unlockTpProcMutex()
326 //return success
327 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000328 }
329 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
330 {
331 if dh.pOnuTP == nil {
332 //should normally not happen ...
333 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000334 log.Fields{"device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000335 return errors.New("TechProfile DelGem request while onuTechProf instance not setup")
336 }
337
338 msgBody := msg.GetBody()
339 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
340 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
341 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000342 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000343 return err
344 }
345
346 //compare TECH_PROFILE_DOWNLOAD_REQUEST
347 dh.pOnuTP.lockTpProcMutex()
mpagenko3dbcdd22020-07-22 07:38:45 +0000348
349 // deadline context to ensure completion of background routines waited for
350 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
351 dctx, cancel := context.WithDeadline(context.Background(), deadline)
352
mpagenko1cc3cb42020-07-27 15:24:38 +0000353 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000354 var wg sync.WaitGroup
355 wg.Add(1) // for the 1 go routine to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000356 go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000357 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
358 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000359 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
360 return err
mpagenkoaf801632020-07-03 10:00:42 +0000361 }
362 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
363 {
364 if dh.pOnuTP == nil {
365 //should normally not happen ...
366 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000367 log.Fields{"device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000368 return errors.New("TechProfile DelTcont request while onuTechProf instance not setup")
369 }
370
371 msgBody := msg.GetBody()
372 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
373 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
374 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000375 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000376 return err
377 }
378
379 //compare TECH_PROFILE_DOWNLOAD_REQUEST
380 dh.pOnuTP.lockTpProcMutex()
381 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify == true {
mpagenko3dbcdd22020-07-22 07:38:45 +0000382 // deadline context to ensure completion of background routines waited for
383 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
384 dctx, cancel := context.WithDeadline(context.Background(), deadline)
385
mpagenko1cc3cb42020-07-27 15:24:38 +0000386 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000387 var wg sync.WaitGroup
mpagenko3dbcdd22020-07-22 07:38:45 +0000388 wg.Add(2) // for the 2 go routines to finish
389 go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000390 cResourceTcont, delTcontMsg.AllocId, &wg)
391 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
mpagenko3dbcdd22020-07-22 07:38:45 +0000392 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000393 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000394 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
395 return err
mpagenkoaf801632020-07-03 10:00:42 +0000396 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000397 dh.pOnuTP.unlockTpProcMutex()
398 //return success
399 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000400 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000401 default:
402 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000403 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000404 "device-id": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000405 return errors.New("unimplemented")
406 }
407 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000408 return nil
409}
410
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000411//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000412// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
413// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300414func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000415 logger.Debugw("disable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000416
mpagenko3af1f032020-06-10 08:53:41 +0000417 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
418 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
419 if dh.deviceReason != "omci-admin-lock" {
420 // disable UNI ports/ONU
421 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
422 // here the result of the processing is not checked (trusted in background) *****
423 if dh.pLockStateFsm == nil {
424 dh.createUniLockFsm(true, UniAdminStateDone)
425 } else { //LockStateFSM already init
426 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
427 dh.runUniLockFsm(true)
428 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300429
mpagenko3af1f032020-06-10 08:53:41 +0000430 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000431 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000432 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000433 }
434 dh.deviceReason = "omci-admin-lock"
435 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
436 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
437 voltha.OperStatus_UNKNOWN); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000438 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000439 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000440 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300441 }
442}
443
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000444//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000445// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
446// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300447func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000448 logger.Debugw("reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000449
450 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300451 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
452 voltha.OperStatus_ACTIVE); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000453 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000454 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300455 }
456
mpagenko3af1f032020-06-10 08:53:41 +0000457 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000458 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000459 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000460 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300461 }
mpagenko3af1f032020-06-10 08:53:41 +0000462 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000463
464 // enable ONU/UNI ports
465 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
466 // here the result of the processing is not checked (trusted in background) *****
467 if dh.pUnlockStateFsm == nil {
468 dh.createUniLockFsm(false, UniAdminStateDone)
469 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000470 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000471 dh.runUniLockFsm(false)
472 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300473}
474
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000475func (dh *DeviceHandler) ReconcileDeviceOnuInd() {
476 logger.Debugw("reconciling - simulate onu indication", log.Fields{"device-id": dh.deviceID})
477
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000478 if err := dh.pOnuTP.restoreFromOnuTpPathKvStore(context.TODO()); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000479 logger.Errorw("reconciling - restoring OnuTp-data failed - abort", log.Fields{"err": err, "device-id": dh.deviceID})
480 dh.reconciling = false
481 return
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000482 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000483 var onu_indication oop.OnuIndication
484 onu_indication.IntfId = dh.pOnuTP.sOnuPersistentData.PersIntfID
485 onu_indication.OnuId = dh.pOnuTP.sOnuPersistentData.PersOnuID
486 onu_indication.OperState = dh.pOnuTP.sOnuPersistentData.PersOperState
487 onu_indication.AdminState = dh.pOnuTP.sOnuPersistentData.PersAdminState
488 dh.create_interface(&onu_indication)
489}
490
491func (dh *DeviceHandler) ReconcileDeviceTechProf() {
492 logger.Debugw("reconciling - trigger tech profile config", log.Fields{"device-id": dh.deviceID})
493
494 dh.pOnuTP.lockTpProcMutex()
495 // lock hangs as long as below decoupled or other related TechProfile processing is active
496 for _, uniData := range dh.pOnuTP.sOnuPersistentData.PersUniTpPath {
497 //In order to allow concurrent calls to other dh instances we do not wait for execution here
498 //but doing so we can not indicate problems to the caller (who does what with that then?)
499 //by now we just assume straightforward successful execution
500 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
501 // possible problems to the caller later autonomously
502
503 // deadline context to ensure completion of background routines waited for
504 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
505 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
506 dctx, cancel := context.WithDeadline(context.Background(), deadline)
507
508 dh.pOnuTP.resetProcessingErrorIndication()
509 var wg sync.WaitGroup
510 wg.Add(1) // for the 1 go routines to finish
511 // attention: deadline completion check and wg.Done is to be done in both routines
512 go dh.pOnuTP.configureUniTp(dctx, uniData.PersUniId, uniData.PersTpPath, &wg)
513 //the wait.. function is responsible for tpProcMutex.Unlock()
514 dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
515 return
516 }
517 dh.pOnuTP.unlockTpProcMutex()
518 //TODO: reset of reconciling-flag has always to be done in the last ReconcileDevice*() function
519 dh.reconciling = false
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000520}
521
522func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000523 logger.Debugw("delete-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000524 if err := dh.pOnuTP.deleteOnuTpPathKvStore(context.TODO()); err != nil {
525 return err
526 }
527 // TODO: further actions - stop metrics and FSMs, remove device ...
528 return nil
529}
530
ozgecanetsiae11479f2020-07-06 09:44:47 +0300531func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000532 logger.Debugw("reboot-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300533 if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
divyadesai4d299552020-08-18 07:13:49 +0000534 logger.Errorw("device-unreachable", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300535 return errors.New("device-unreachable")
536 }
537 dh.pOnuOmciDevice.Reboot(context.TODO())
538 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
539 voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000540 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000541 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300542 return err
543 }
544 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting-onu"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000545 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000546 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300547 return err
548 }
549 dh.deviceReason = "rebooting-onu"
550 return nil
551}
552
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000553// DeviceHandler methods that implement the adapters interface requests## end #########
554// #####################################################################################
555
556// ################ to be updated acc. needs of ONU Device ########################
557// DeviceHandler StateMachine related state transition methods ##### begin #########
558
559func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
560 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})
561}
562
563// doStateInit provides the device update to the core
564func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
565
566 logger.Debug("doStateInit-started")
567 var err error
568
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000569 // populate what we know. rest comes later after mib sync
570 dh.device.Root = false
571 dh.device.Vendor = "OpenONU"
572 dh.device.Model = "go"
573 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000574 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000575
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000576 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000577
578 if !dh.reconciling {
579 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
580 } else {
581 logger.Debugw("reconciling - don't notify core about DeviceUpdate",
582 log.Fields{"device-id": dh.deviceID})
583 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000584
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000585 dh.parentId = dh.device.ParentId
586 dh.ponPortNumber = dh.device.ParentPortNo
587
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000588 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
589 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
590 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
divyadesai4d299552020-08-18 07:13:49 +0000591 logger.Debugw("device-updated", log.Fields{"device-id": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000592 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000593 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000594
595 /*
596 self._pon = PonPort.create(self, self._pon_port_number)
597 self._pon.add_peer(self.parent_id, self._pon_port_number)
598 self.logger.debug('adding-pon-port-to-agent',
599 type=self._pon.get_port().type,
600 admin_state=self._pon.get_port().admin_state,
601 oper_status=self._pon.get_port().oper_status,
602 )
603 */
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000604 if !dh.reconciling {
605 logger.Debugw("adding-pon-port", log.Fields{"deviceID": dh.deviceID, "ponPortNo": dh.ponPortNumber})
606 var ponPortNo uint32 = 1
607 if dh.ponPortNumber != 0 {
608 ponPortNo = dh.ponPortNumber
609 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000610
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000611 pPonPort := &voltha.Port{
612 PortNo: ponPortNo,
613 Label: fmt.Sprintf("pon-%d", ponPortNo),
614 Type: voltha.Port_PON_ONU,
615 OperStatus: voltha.OperStatus_ACTIVE,
616 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
617 PortNo: ponPortNo}}, // Peer port is parent's port number
618 }
619 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
620 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
621 e.Cancel(err)
622 return
623 }
624 } else {
625 logger.Debugw("reconciling - pon-port already added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000626 }
627 logger.Debug("doStateInit-done")
628}
629
630// postInit setups the DeviceEntry for the conerned device
631func (dh *DeviceHandler) postInit(e *fsm.Event) {
632
633 logger.Debug("postInit-started")
634 var err error
635 /*
636 dh.Client = oop.NewOpenoltClient(dh.clientCon)
637 dh.pTransitionMap.Handle(ctx, GrpcConnected)
638 return nil
639 */
mpagenko3af1f032020-06-10 08:53:41 +0000640 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
641 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000642 e.Cancel(err)
643 return
644 }
645
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000646 if dh.reconciling {
647 go dh.ReconcileDeviceOnuInd()
648 // reconcilement will be continued after mib download is done
649 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000650 /*
651 ############################################################################
652 # Setup Alarm handler
653 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
654 device.serial_number)
655 ############################################################################
656 # Setup PM configuration for this device
657 # Pass in ONU specific options
658 kwargs = {
659 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
660 'heartbeat': self.heartbeat,
661 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
662 }
663 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
664 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
665 self.logical_device_id, device.serial_number,
666 grouped=True, freq_override=False, **kwargs)
667 pm_config = self._pm_metrics.make_proto()
668 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
669 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
670 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
671
672 # Note, ONU ID and UNI intf set in add_uni_port method
673 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
674 ani_ports=[self._pon])
675
676 # Code to Run OMCI Test Action
677 kwargs_omci_test_action = {
678 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
679 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
680 }
681 serial_number = device.serial_number
682 self._test_request = OmciTestRequest(self.core_proxy,
683 self.omci_agent, self.device_id,
684 AniG, serial_number,
685 self.logical_device_id,
686 exclusive=False,
687 **kwargs_omci_test_action)
688
689 self.enabled = True
690 else:
691 self.logger.info('onu-already-activated')
692 */
693 logger.Debug("postInit-done")
694}
695
696// doStateConnected get the device info and update to voltha core
697// for comparison of the original method (not that easy to uncomment): compare here:
698// voltha-openolt-adapter/adaptercore/device_handler.go
699// -> this one obviously initiates all communication interfaces of the device ...?
700func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
701
702 logger.Debug("doStateConnected-started")
703 var err error
704 err = errors.New("Device FSM: function not implemented yet!")
705 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000706 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700707 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000708}
709
710// doStateUp handle the onu up indication and update to voltha core
711func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
712
713 logger.Debug("doStateUp-started")
714 var err error
715 err = errors.New("Device FSM: function not implemented yet!")
716 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000717 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700718 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000719
720 /*
721 // Synchronous call to update device state - this method is run in its own go routine
722 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
723 voltha.OperStatus_ACTIVE); err != nil {
724 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
725 return err
726 }
727 return nil
728 */
729}
730
731// doStateDown handle the onu down indication
732func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
733
734 logger.Debug("doStateDown-started")
735 var err error
736
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000737 device := dh.device
738 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000739 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000740 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000741 e.Cancel(err)
742 return
743 }
744
745 cloned := proto.Clone(device).(*voltha.Device)
746 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
747 /*
748 // Update the all ports state on that device to disable
749 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
750 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
751 return er
752 }
753
754 //Update the device oper state and connection status
755 cloned.OperStatus = voltha.OperStatus_UNKNOWN
756 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
757 dh.device = cloned
758
759 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
760 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
761 return er
762 }
763
764 //get the child device for the parent device
765 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
766 if err != nil {
767 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
768 return err
769 }
770 for _, onuDevice := range onuDevices.Items {
771
772 // Update onu state as down in onu adapter
773 onuInd := oop.OnuIndication{}
774 onuInd.OperState = "down"
775 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
776 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
777 if er != nil {
778 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
779 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
780 //Do not return here and continue to process other ONUs
781 }
782 }
783 // * Discovered ONUs entries need to be cleared , since after OLT
784 // is up, it starts sending discovery indications again* /
785 dh.discOnus = sync.Map{}
786 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
787 return nil
788 */
789 err = errors.New("Device FSM: function not implemented yet!")
790 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000791 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700792 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000793}
794
795// DeviceHandler StateMachine related state transition methods ##### end #########
796// #################################################################################
797
798// ###################################################
799// DeviceHandler utility methods ##### begin #########
800
mpagenko3af1f032020-06-10 08:53:41 +0000801//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
802func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
803 dh.lockDevice.RLock()
804 pOnuDeviceEntry := dh.pOnuOmciDevice
805 if aWait && pOnuDeviceEntry == nil {
806 //keep the read sema short to allow for subsequent write
807 dh.lockDevice.RUnlock()
divyadesai4d299552020-08-18 07:13:49 +0000808 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000809 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
810 // so it might be needed to wait here for that event with some timeout
811 select {
812 case <-time.After(60 * time.Second): //timer may be discussed ...
divyadesai4d299552020-08-18 07:13:49 +0000813 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000814 return nil
815 case <-dh.deviceEntrySet:
divyadesai4d299552020-08-18 07:13:49 +0000816 logger.Debugw("devicEntry ready now - continue", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000817 // if written now, we can return the written value without sema
818 return dh.pOnuOmciDevice
819 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000820 }
mpagenko3af1f032020-06-10 08:53:41 +0000821 dh.lockDevice.RUnlock()
822 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000823}
824
mpagenko3af1f032020-06-10 08:53:41 +0000825//SetOnuDeviceEntry sets the ONU device entry within the handler
mpagenkoaf801632020-07-03 10:00:42 +0000826func (dh *DeviceHandler) SetOnuDeviceEntry(
827 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000828 dh.lockDevice.Lock()
829 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000830 dh.pOnuOmciDevice = apDeviceEntry
831 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000832 return nil
833}
834
mpagenko3af1f032020-06-10 08:53:41 +0000835//AddOnuDeviceEntry creates a new ONU device or returns the existing
836func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
divyadesai4d299552020-08-18 07:13:49 +0000837 logger.Debugw("adding-deviceEntry", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000838
mpagenko3af1f032020-06-10 08:53:41 +0000839 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000840 if deviceEntry == nil {
841 /* costum_me_map in python code seems always to be None,
842 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
843 /* also no 'clock' argument - usage open ...*/
844 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000845 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
846 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000847 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000848 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000849 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000850 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000851 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000852 // fire deviceEntry ready event to spread to possibly waiting processing
853 dh.deviceEntrySet <- true
divyadesai4d299552020-08-18 07:13:49 +0000854 logger.Infow("onuDeviceEntry-added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000855 } else {
divyadesai4d299552020-08-18 07:13:49 +0000856 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000857 }
858 // might be updated with some error handling !!!
859 return nil
860}
861
862// doStateInit provides the device update to the core
863func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000864 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
865 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
866
867 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000868
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000869 if !dh.reconciling {
870 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
871 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
872 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
873 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
874 }
875 } else {
876 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVATING",
877 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000878 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000879 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
880 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
881 // 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 +0000882 // 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 +0000883 // so let's just try to keep it simple ...
884 /*
885 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
886 if err != nil || device == nil {
887 //TODO: needs to handle error scenarios
888 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
889 return errors.New("Voltha Device not found")
890 }
891 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000892
mpagenko3af1f032020-06-10 08:53:41 +0000893 pDevEntry := dh.GetOnuDeviceEntry(true)
894 if pDevEntry != nil {
895 pDevEntry.Start(context.TODO())
896 } else {
divyadesai4d299552020-08-18 07:13:49 +0000897 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000898 return errors.New("No valid OnuDevice")
899 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000900 if !dh.reconciling {
901 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
902 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
903 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"device-id": dh.deviceID, "error": err})
904 }
905 } else {
906 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to starting-openomci",
907 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000908 }
mpagenko3af1f032020-06-10 08:53:41 +0000909 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000910
911 /* this might be a good time for Omci Verify message? */
912 verifyExec := make(chan bool)
913 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000914 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000915 true, true) //eclusive and allowFailure (anyway not yet checked)
916 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
917
918 /* give the handler some time here to wait for the OMCi verification result
919 after Timeout start and try MibUpload FSM anyway
920 (to prevent stopping on just not supported OMCI verification from ONU) */
921 select {
922 case <-time.After(2 * time.Second):
923 logger.Warn("omci start-verification timed out (continue normal)")
924 case testresult := <-verifyExec:
925 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
926 }
927
928 /* In py code it looks earlier (on activate ..)
929 # Code to Run OMCI Test Action
930 kwargs_omci_test_action = {
931 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
932 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
933 }
934 serial_number = device.serial_number
935 self._test_request = OmciTestRequest(self.core_proxy,
936 self.omci_agent, self.device_id,
937 AniG, serial_number,
938 self.logical_device_id,
939 exclusive=False,
940 **kwargs_omci_test_action)
941 ...
942 # Start test requests after a brief pause
943 if not self._test_request_started:
944 self._test_request_started = True
945 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
946 reactor.callLater(tststart, self._test_request.start_collector)
947
948 */
949 /* which is then: in omci_test_request.py : */
950 /*
951 def start_collector(self, callback=None):
952 """
953 Start the collection loop for an adapter if the frequency > 0
954
955 :param callback: (callable) Function to call to collect PM data
956 """
957 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
958 if callback is None:
959 callback = self.perform_test_omci
960
961 if self.lc is None:
962 self.lc = LoopingCall(callback)
963
964 if self.default_freq > 0:
965 self.lc.start(interval=self.default_freq / 10)
966
967 def perform_test_omci(self):
968 """
969 Perform the initial test request
970 """
971 ani_g_entities = self._device.configuration.ani_g_entities
972 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
973 is not None else None
974 self._entity_id = ani_g_entities_ids[0]
975 self.logger.info('perform-test', entity_class=self._entity_class,
976 entity_id=self._entity_id)
977 try:
978 frame = MEFrame(self._entity_class, self._entity_id, []).test()
979 result = yield self._device.omci_cc.send(frame)
980 if not result.fields['omci_message'].fields['success_code']:
981 self.logger.info('Self-Test Submitted Successfully',
982 code=result.fields[
983 'omci_message'].fields['success_code'])
984 else:
985 raise TestFailure('Test Failure: {}'.format(
986 result.fields['omci_message'].fields['success_code']))
987 except TimeoutError as e:
988 self.deferred.errback(failure.Failure(e))
989
990 except Exception as e:
991 self.logger.exception('perform-test-Error', e=e,
992 class_id=self._entity_class,
993 entity_id=self._entity_id)
994 self.deferred.errback(failure.Failure(e))
995
996 */
997
998 // PM related heartbeat??? !!!TODO....
999 //self._heartbeat.enabled = True
1000
mpagenko1cc3cb42020-07-27 15:24:38 +00001001 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
1002 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
1003 * as further OltAdapter processing may rely on the deviceReason event 'MibUploadDone' as a result of the FSM processing
1004 * otherwise some processing synchronisation would be required - cmp. e.g TechProfile processing
1005 */
1006 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +00001007 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001008 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001009 if pMibUlFsm.Is(ulStDisabled) {
1010 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001011 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
1012 return errors.New("Can't go to state starting")
1013 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001014 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001015 //Determine ONU status and start/re-start MIB Synchronization tasks
1016 //Determine if this ONU has ever synchronized
1017 if true { //TODO: insert valid check
mpagenko1cc3cb42020-07-27 15:24:38 +00001018 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001019 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
1020 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001021 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001022 } else {
mpagenko1cc3cb42020-07-27 15:24:38 +00001023 pMibUlFsm.Event(ulEvExamineMds)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001024 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001025 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001026 // callbacks to be handled:
mpagenko1cc3cb42020-07-27 15:24:38 +00001027 // Event(ulEvSuccess)
1028 // Event(ulEvTimeout)
1029 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001030 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001031 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001032 } else {
1033 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
1034 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001035 }
1036 } else {
divyadesai4d299552020-08-18 07:13:49 +00001037 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001038 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001039 }
1040 return nil
1041}
1042
mpagenko3af1f032020-06-10 08:53:41 +00001043func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
1044 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
1045 if dh.deviceReason != "stopping-openomci" {
divyadesai4d299552020-08-18 07:13:49 +00001046 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001047 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
1048 pDevEntry := dh.GetOnuDeviceEntry(false)
1049 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001050 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001051 return errors.New("No valid OnuDevice")
1052 }
1053
1054 switch dh.deviceReason {
1055 case "starting-openomci":
1056 { //MIBSync FSM may run
1057 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
1058 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001059 pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +00001060 }
1061 }
1062 case "discovery-mibsync-complete":
1063 { //MibDownload may run
1064 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1065 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001066 pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001067 }
1068 }
1069 default:
mpagenko3dbcdd22020-07-22 07:38:45 +00001070 {
1071 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +00001072 if dh.pUnlockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001073 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001074 }
1075 if dh.pLockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001076 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001077 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001078 //techProfile related PonAniConfigFsm FSM may be active
1079 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
1080 if dh.pOnuTP.pAniConfigFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001081 dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +00001082 }
mpagenko3af1f032020-06-10 08:53:41 +00001083 }
1084 //TODO!!! care about PM/Alarm processing once started
1085 }
1086 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
1087 // (mainly the still seperate 'Event states')
1088 // so it is questionable, how this is resolved after some possible re-enable
1089 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1090
1091 //stop/remove(?) the device entry
1092 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
1093
1094 //TODO!!! remove existing traffic profiles
1095 /* from py code, if TP's exist, remove them - not yet implemented
1096 self._tp = dict()
1097 # Let TP download happen again
1098 for uni_id in self._tp_service_specific_task:
1099 self._tp_service_specific_task[uni_id].clear()
1100 for uni_id in self._tech_profile_download_done:
1101 self._tech_profile_download_done[uni_id].clear()
1102 */
1103
1104 dh.disableUniPortStateUpdate()
1105
1106 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001107 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001108 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
divyadesai4d299552020-08-18 07:13:49 +00001109 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001110 // abort: system behavior is just unstable ...
1111 return err
1112 }
1113 dh.deviceReason = "stopping-openomci"
1114
1115 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1116 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001117 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001118 logger.Errorw("error-updating-device-state unreachable-discovered",
divyadesai4d299552020-08-18 07:13:49 +00001119 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001120 // abort: system behavior is just unstable ...
1121 return err
1122 }
1123 } else {
divyadesai4d299552020-08-18 07:13:49 +00001124 logger.Debugw("updateInterface - device already stopped", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001125 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001126 return nil
1127}
1128
mpagenko3af1f032020-06-10 08:53:41 +00001129//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001130func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
1131 switch dev_Event {
1132 case MibDatabaseSync:
1133 {
divyadesai4d299552020-08-18 07:13:49 +00001134 logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001135 if !dh.reconciling {
1136 //initiate DevStateUpdate
1137 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1138 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1139 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1140 "device-id": dh.deviceID, "error": err})
1141 } else {
1142 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
1143 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001144 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001145 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
1146 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001147 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001148 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001149 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001150
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001151 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001152 pDevEntry := dh.GetOnuDeviceEntry(false)
1153 if unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001154 for _, mgmtEntityId := range unigInstKeys {
1155 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001156 "device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001157 dh.addUniPort(mgmtEntityId, i, UniPPTP)
1158 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001159 }
1160 } else {
divyadesai4d299552020-08-18 07:13:49 +00001161 logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001162 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001163 if veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001164 for _, mgmtEntityId := range veipInstKeys {
1165 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001166 "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityId})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001167 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1168 i++
1169 }
1170 } else {
divyadesai4d299552020-08-18 07:13:49 +00001171 logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001172 }
1173 if i == 0 {
divyadesai4d299552020-08-18 07:13:49 +00001174 logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001175 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001176
mpagenko3af1f032020-06-10 08:53:41 +00001177 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1178 * left the code here as comment in case such processing should prove needed unexpectedly
1179 // Init Uni Ports to Admin locked state
1180 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1181 // *** should generate UniLockStateDone event *****
1182 if dh.pLockStateFsm == nil {
1183 dh.createUniLockFsm(true, UniLockStateDone)
1184 } else { //LockStateFSM already init
1185 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1186 dh.runUniLockFsm(true)
1187 }
1188 }
1189 case UniLockStateDone:
1190 {
divyadesai4d299552020-08-18 07:13:49 +00001191 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001192 * lockState processing commented out
1193 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001194 /* Mib download procedure -
1195 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1196 */
mpagenko3af1f032020-06-10 08:53:41 +00001197 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001198 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001199 if pMibDlFsm.Is(dlStDisabled) {
1200 if err := pMibDlFsm.Event(dlEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001201 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1202 // maybe try a FSM reset and then again ... - TODO!!!
1203 } else {
1204 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1205 // maybe use more specific states here for the specific download steps ...
mpagenko1cc3cb42020-07-27 15:24:38 +00001206 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001207 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1208 } else {
1209 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1210 //Begin MIB data download (running autonomously)
1211 }
1212 }
1213 } else {
1214 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1215 // maybe try a FSM reset and then again ... - TODO!!!
1216 }
1217 /***** Mib download started */
1218 } else {
divyadesai4d299552020-08-18 07:13:49 +00001219 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001220 }
1221 }
1222 case MibDownloadDone:
1223 {
divyadesai4d299552020-08-18 07:13:49 +00001224 logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001225 //initiate DevStateUpdate
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001226 if !dh.reconciling {
1227 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1228 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1229 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1230 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1231 } else {
1232 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
1233 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001234 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001235 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
1236 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001237 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001238 if !dh.reconciling {
1239 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1240 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1241 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1242 log.Fields{"device-id": dh.deviceID, "error": err})
1243 } else {
1244 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
1245 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001246 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001247 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
1248 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001249 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001250 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001251 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001252 // *** should generate UniUnlockStateDone event *****
1253 if dh.pUnlockStateFsm == nil {
1254 dh.createUniLockFsm(false, UniUnlockStateDone)
1255 } else { //UnlockStateFSM already init
1256 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1257 dh.runUniLockFsm(false)
1258 }
1259 }
1260 case UniUnlockStateDone:
1261 {
mpagenko3af1f032020-06-10 08:53:41 +00001262 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001263
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001264 if !dh.reconciling {
1265 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
1266 raisedTs := time.Now().UnixNano()
1267 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1268 } else {
1269 logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
1270 log.Fields{"device-id": dh.deviceID})
1271 go dh.ReconcileDeviceTechProf()
1272 //TODO: further actions e.g. restore flows, metrics, ...
1273 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001274 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001275 case OmciAniConfigDone:
1276 {
divyadesai4d299552020-08-18 07:13:49 +00001277 logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001278 //TODO!: it might be needed to check some 'cached' pending flow configuration (vlan setting)
1279 // - to consider with outstanding flow implementation
1280 // attention: the device reason update is done based on ONU-UNI-Port related activity
1281 // - which may cause some inconsistency
1282 if dh.deviceReason != "tech-profile-config-download-success" {
1283 // which may be the case from some previous actvity on another UNI Port of the ONU
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001284 if !dh.reconciling {
1285 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1286 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1287 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1288 log.Fields{"device-id": dh.deviceID, "error": err})
1289 } else {
1290 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1291 log.Fields{"device-id": dh.deviceID})
1292 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001293 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001294 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
divyadesai4d299552020-08-18 07:13:49 +00001295 log.Fields{"device-id": dh.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001296 }
1297 //set internal state anyway - as it was done
1298 dh.deviceReason = "tech-profile-config-download-success"
1299 }
1300 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001301 default:
1302 {
divyadesai4d299552020-08-18 07:13:49 +00001303 logger.Warnw("unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": dev_Event})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001304 }
1305 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001306}
1307
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001308func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001309 // parameters are IntfId, OnuId, uniId
1310 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1311 uint32(a_uniId))
1312 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001313 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1314 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001315 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001316 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001317 if pUniPort == nil {
1318 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1319 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001320 //store UniPort with the System-PortNumber key
1321 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001322 if !dh.reconciling {
1323 // create announce the UniPort to the core as VOLTHA Port object
1324 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1325 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1326 } //error logging already within UniPort method
1327 } else {
1328 logger.Debugw("reconciling - onuUniPort already added", log.Fields{"for PortNo": uniNo, "device-id": dh.deviceID})
1329 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001330 }
1331 }
1332}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001333
mpagenko3af1f032020-06-10 08:53:41 +00001334// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1335func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001336 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1337 // but towards core only the first port active state is signalled
1338 // with following remark:
1339 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1340 // # load on the core
1341
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001342 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001343
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001344 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001345 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001346 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1347 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1348 uniPort.SetOperState(vc.OperStatus_ACTIVE)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001349 if !dh.reconciling {
1350 //maybe also use getter functions on uniPort - perhaps later ...
1351 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1352 } else {
1353 logger.Debugw("reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
1354 }
mpagenko3af1f032020-06-10 08:53:41 +00001355 }
1356 }
1357}
1358
1359// Disable UniPortState and update core port state accordingly
1360func (dh *DeviceHandler) disableUniPortStateUpdate() {
1361 // compare enableUniPortStateUpdate() above
1362 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1363 for uniNo, uniPort := range dh.uniEntityMap {
1364 // only if this port is validated for operState transfer
1365 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1366 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1367 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1368 //maybe also use getter functions on uniPort - perhaps later ...
1369 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001370 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001371 }
1372}
1373
1374// ONU_Active/Inactive announcement on system KAFKA bus
1375// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1376func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1377 var de voltha.DeviceEvent
1378 eventContext := make(map[string]string)
1379 //Populating event context
1380 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1381 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1382 if err != nil || parentDevice == nil {
1383 logger.Errorw("Failed to fetch parent device for OnuEvent",
1384 log.Fields{"parentId": dh.parentId, "err": err})
1385 }
1386 oltSerialNumber := parentDevice.SerialNumber
1387
1388 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1389 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1390 eventContext["serial-number"] = dh.device.SerialNumber
1391 eventContext["olt_serial_number"] = oltSerialNumber
1392 eventContext["device_id"] = a_deviceID
1393 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1394 logger.Debugw("prepare ONU_ACTIVATED event",
1395 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1396
1397 /* Populating device event body */
1398 de.Context = eventContext
1399 de.ResourceId = a_deviceID
1400 if a_OperState == voltha.OperStatus_ACTIVE {
1401 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1402 de.Description = fmt.Sprintf("%s Event - %s - %s",
1403 cEventObjectType, cOnuActivatedEvent, "Raised")
1404 } else {
1405 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1406 de.Description = fmt.Sprintf("%s Event - %s - %s",
1407 cEventObjectType, cOnuActivatedEvent, "Cleared")
1408 }
1409 /* Send event to KAFKA */
1410 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1411 logger.Warnw("could not send ONU_ACTIVATED event",
divyadesai4d299552020-08-18 07:13:49 +00001412 log.Fields{"device-id": a_deviceID, "error": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001413 }
1414 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
divyadesai4d299552020-08-18 07:13:49 +00001415 log.Fields{"device-id": a_deviceID, "with-EventName": de.DeviceEventName})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001416}
1417
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001418// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
1419func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1420 chLSFsm := make(chan Message, 2048)
1421 var sFsmName string
1422 if aAdminState == true {
divyadesai4d299552020-08-18 07:13:49 +00001423 logger.Infow("createLockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001424 sFsmName = "LockStateFSM"
1425 } else {
divyadesai4d299552020-08-18 07:13:49 +00001426 logger.Infow("createUnlockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001427 sFsmName = "UnLockStateFSM"
1428 }
mpagenko3af1f032020-06-10 08:53:41 +00001429
1430 pDevEntry := dh.GetOnuDeviceEntry(true)
1431 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001432 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001433 return
1434 }
1435 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001436 sFsmName, dh.deviceID, chLSFsm)
1437 if pLSFsm != nil {
1438 if aAdminState == true {
1439 dh.pLockStateFsm = pLSFsm
1440 } else {
1441 dh.pUnlockStateFsm = pLSFsm
1442 }
1443 dh.runUniLockFsm(aAdminState)
1444 } else {
divyadesai4d299552020-08-18 07:13:49 +00001445 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001446 }
1447}
1448
1449// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1450func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1451 /* Uni Port lock/unlock procedure -
1452 ***** should run via 'adminDone' state and generate the argument requested event *****
1453 */
1454 var pLSStatemachine *fsm.FSM
1455 if aAdminState == true {
1456 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1457 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1458 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001459 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1460 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001461 }
1462 } else {
1463 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1464 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1465 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001466 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1467 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001468 }
1469 }
1470 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001471 if pLSStatemachine.Is(uniStDisabled) {
1472 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001473 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1474 // maybe try a FSM reset and then again ... - TODO!!!
1475 } else {
1476 /***** LockStateFSM started */
1477 logger.Debugw("LockStateFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001478 "state": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001479 }
1480 } else {
1481 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001482 "have": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001483 // maybe try a FSM reset and then again ... - TODO!!!
1484 }
1485 } else {
divyadesai4d299552020-08-18 07:13:49 +00001486 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001487 // maybe try a FSM reset and then again ... - TODO!!!
1488 }
1489}
1490
mpagenkoaf801632020-07-03 10:00:42 +00001491//SetBackend provides a DB backend for the specified path on the existing KV client
1492func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1493 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1494 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
divyadesai4d299552020-08-18 07:13:49 +00001495 "BasePathKvStore": aBasePathKvStore, "device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +00001496 kvbackend := &db.Backend{
1497 Client: dh.pOpenOnuAc.kvClient,
1498 StoreType: dh.pOpenOnuAc.KVStoreType,
1499 /* address config update acc. to [VOL-2736] */
1500 Address: addr,
1501 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1502 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001503
mpagenkoaf801632020-07-03 10:00:42 +00001504 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001505}