blob: f8bf361e5454538672b8ee3ea2b537e19eb5b627 [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"
mpagenkodff5dda2020-08-28 11:52:01 +000035 flow "github.com/opencord/voltha-lib-go/v3/pkg/flows"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000036 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000037 vc "github.com/opencord/voltha-protos/v3/go/common"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000038 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
mpagenkodff5dda2020-08-28 11:52:01 +000039 "github.com/opencord/voltha-protos/v3/go/openflow_13"
40 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
41 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000042 oop "github.com/opencord/voltha-protos/v3/go/openolt"
43 "github.com/opencord/voltha-protos/v3/go/voltha"
44)
45
46/*
47// Constants for number of retries and for timeout
48const (
49 MaxRetry = 10
50 MaxTimeOutInMs = 500
51)
52*/
53
mpagenko1cc3cb42020-07-27 15:24:38 +000054const (
55 // events of Device FSM
56 devEvDeviceInit = "devEvDeviceInit"
57 devEvGrpcConnected = "devEvGrpcConnected"
58 devEvGrpcDisconnected = "devEvGrpcDisconnected"
59 devEvDeviceUpInd = "devEvDeviceUpInd"
60 devEvDeviceDownInd = "devEvDeviceDownInd"
61)
62const (
63 // states of Device FSM
64 devStNull = "devStNull"
65 devStDown = "devStDown"
66 devStInit = "devStInit"
67 devStConnected = "devStConnected"
68 devStUp = "devStUp"
69)
70
Holger Hildebrandt24d51952020-05-04 14:03:42 +000071//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
72const (
Himani Chawla4d908332020-08-31 12:30:20 +053073 pon = voltha.EventSubCategory_PON
74 //olt = voltha.EventSubCategory_OLT
75 //ont = voltha.EventSubCategory_ONT
76 //onu = voltha.EventSubCategory_ONU
77 //nni = voltha.EventSubCategory_NNI
78 //service = voltha.EventCategory_SERVICE
79 //security = voltha.EventCategory_SECURITY
80 equipment = voltha.EventCategory_EQUIPMENT
81 //processing = voltha.EventCategory_PROCESSING
82 //environment = voltha.EventCategory_ENVIRONMENT
83 //communication = voltha.EventCategory_COMMUNICATION
Holger Hildebrandt24d51952020-05-04 14:03:42 +000084)
85
86const (
87 cEventObjectType = "ONU"
88)
89const (
90 cOnuActivatedEvent = "ONU_ACTIVATED"
91)
92
Himani Chawla6d2ae152020-09-02 13:11:20 +053093//deviceHandler will interact with the ONU ? device.
94type deviceHandler struct {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000095 deviceID string
96 DeviceType string
97 adminState string
98 device *voltha.Device
99 logicalDeviceID string
100 ProxyAddressID string
101 ProxyAddressType string
Himani Chawla4d908332020-08-31 12:30:20 +0530102 parentID string
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000103 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000104
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000105 coreProxy adapterif.CoreProxy
106 AdapterProxy adapterif.AdapterProxy
107 EventProxy adapterif.EventProxy
108
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000109 pOpenOnuAc *OpenONUAC
110 pDeviceStateFsm *fsm.FSM
Himani Chawla4d908332020-08-31 12:30:20 +0530111 //pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +0000112 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000113 pOnuOmciDevice *OnuDeviceEntry
Himani Chawla6d2ae152020-09-02 13:11:20 +0530114 pOnuTP *onuUniTechProf
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000115 exitChannel chan int
116 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000117 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +0000118 deviceReason string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530119 pLockStateFsm *lockStateFsm
120 pUnlockStateFsm *lockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000121
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000122 //flowMgr *OpenOltFlowMgr
123 //eventMgr *OpenOltEventMgr
124 //resourceMgr *rsrcMgr.OpenOltResourceMgr
125
126 //discOnus sync.Map
127 //onus sync.Map
128 //portStats *OpenOltStatisticsMgr
129 //metrics *pmmetrics.PmMetrics
mpagenkodff5dda2020-08-28 11:52:01 +0000130 stopCollector chan bool
131 stopHeartbeatCheck chan bool
132 activePorts sync.Map
Himani Chawla6d2ae152020-09-02 13:11:20 +0530133 uniEntityMap map[uint32]*onuUniPort
mpagenkodff5dda2020-08-28 11:52:01 +0000134 UniVlanConfigFsmMap map[uint8]*UniVlanConfigFsm
135 reconciling bool
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000136}
137
Himani Chawla6d2ae152020-09-02 13:11:20 +0530138//newDeviceHandler creates a new device handler
139func newDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *deviceHandler {
140 var dh deviceHandler
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000141 dh.coreProxy = cp
142 dh.AdapterProxy = ap
143 dh.EventProxy = ep
144 cloned := (proto.Clone(device)).(*voltha.Device)
145 dh.deviceID = cloned.Id
146 dh.DeviceType = cloned.Type
147 dh.adminState = "up"
148 dh.device = cloned
149 dh.pOpenOnuAc = adapter
150 dh.exitChannel = make(chan int, 1)
151 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000152 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000153 dh.stopCollector = make(chan bool, 2)
154 dh.stopHeartbeatCheck = make(chan bool, 2)
155 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
156 dh.activePorts = sync.Map{}
157 //TODO initialize the support classes.
Himani Chawla6d2ae152020-09-02 13:11:20 +0530158 dh.uniEntityMap = make(map[uint32]*onuUniPort)
mpagenkodff5dda2020-08-28 11:52:01 +0000159 dh.UniVlanConfigFsmMap = make(map[uint8]*UniVlanConfigFsm)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000160 dh.reconciling = false
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000161
162 // Device related state machine
163 dh.pDeviceStateFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000164 devStNull,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000165 fsm.Events{
mpagenko1cc3cb42020-07-27 15:24:38 +0000166 {Name: devEvDeviceInit, Src: []string{devStNull, devStDown}, Dst: devStInit},
167 {Name: devEvGrpcConnected, Src: []string{devStInit}, Dst: devStConnected},
168 {Name: devEvGrpcDisconnected, Src: []string{devStConnected, devStDown}, Dst: devStInit},
169 {Name: devEvDeviceUpInd, Src: []string{devStConnected, devStDown}, Dst: devStUp},
170 {Name: devEvDeviceDownInd, Src: []string{devStUp}, Dst: devStDown},
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000171 },
172 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000173 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
174 ("before_" + devEvDeviceInit): func(e *fsm.Event) { dh.doStateInit(e) },
175 ("after_" + devEvDeviceInit): func(e *fsm.Event) { dh.postInit(e) },
176 ("before_" + devEvGrpcConnected): func(e *fsm.Event) { dh.doStateConnected(e) },
177 ("before_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.doStateInit(e) },
178 ("after_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.postInit(e) },
179 ("before_" + devEvDeviceUpInd): func(e *fsm.Event) { dh.doStateUp(e) },
180 ("before_" + devEvDeviceDownInd): func(e *fsm.Event) { dh.doStateDown(e) },
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000181 },
182 )
mpagenkoaf801632020-07-03 10:00:42 +0000183
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000184 return &dh
185}
186
Himani Chawla6d2ae152020-09-02 13:11:20 +0530187// start save the device to the data model
188func (dh *deviceHandler) start(ctx context.Context) {
divyadesai4d299552020-08-18 07:13:49 +0000189 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000190 // Add the initial device to the local model
191 logger.Debug("device-handler-started")
192}
193
Himani Chawla4d908332020-08-31 12:30:20 +0530194/*
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000195// stop stops the device dh. Not much to do for now
Himani Chawla6d2ae152020-09-02 13:11:20 +0530196func (dh *deviceHandler) stop(ctx context.Context) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000197 logger.Debug("stopping-device-handler")
198 dh.exitChannel <- 1
199}
Himani Chawla4d908332020-08-31 12:30:20 +0530200*/
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000201
202// ##########################################################################################
Himani Chawla6d2ae152020-09-02 13:11:20 +0530203// deviceHandler methods that implement the adapters interface requests ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000204
Himani Chawla6d2ae152020-09-02 13:11:20 +0530205//adoptOrReconcileDevice adopts the OLT device
206func (dh *deviceHandler) adoptOrReconcileDevice(ctx context.Context, device *voltha.Device) {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000207 logger.Debugw("Adopt_or_reconcile_device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000208
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000209 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
mpagenko1cc3cb42020-07-27 15:24:38 +0000210 if dh.pDeviceStateFsm.Is(devStNull) {
211 if err := dh.pDeviceStateFsm.Event(devEvDeviceInit); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000212 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
213 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000214 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000215 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000216 logger.Debugw("AdoptOrReconcileDevice: Agent/device init already done", log.Fields{"device-id": device.Id})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000217 }
218
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000219}
220
Himani Chawla6d2ae152020-09-02 13:11:20 +0530221func (dh *deviceHandler) processInterAdapterOMCIReqMessage(msg *ic.InterAdapterMessage) error {
Himani Chawla26e555c2020-08-31 12:30:20 +0530222 msgBody := msg.GetBody()
223 omciMsg := &ic.InterAdapterOmciMessage{}
224 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
225 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
226 "device-id": dh.deviceID, "error": err})
227 return err
228 }
229
230 //assuming omci message content is hex coded!
231 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
232 logger.Debugw("inter-adapter-recv-omci", log.Fields{
233 "device-id": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
234 //receive_message(omci_msg.message)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530235 pDevEntry := dh.getOnuDeviceEntry(true)
Himani Chawla26e555c2020-08-31 12:30:20 +0530236 if pDevEntry != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530237 return pDevEntry.PDevOmciCC.receiveMessage(context.TODO(), omciMsg.Message)
Himani Chawla26e555c2020-08-31 12:30:20 +0530238 }
239 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000240 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530241}
242
Himani Chawla6d2ae152020-09-02 13:11:20 +0530243func (dh *deviceHandler) processInterAdapterONUIndReqMessage(msg *ic.InterAdapterMessage) error {
Himani Chawla26e555c2020-08-31 12:30:20 +0530244 msgBody := msg.GetBody()
245 onuIndication := &oop.OnuIndication{}
246 if err := ptypes.UnmarshalAny(msgBody, onuIndication); err != nil {
247 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
248 "device-id": dh.deviceID, "error": err})
249 return err
250 }
251
252 onuOperstate := onuIndication.GetOperState()
253 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onuIndication.GetOnuId(),
254 "AdminState": onuIndication.GetAdminState(), "OperState": onuOperstate,
255 "SNR": onuIndication.GetSerialNumber()})
256
257 //interface related functions might be error checked ....
258 if onuOperstate == "up" {
259 _ = dh.createInterface(onuIndication)
260 } else if (onuOperstate == "down") || (onuOperstate == "unreachable") {
261 _ = dh.updateInterface(onuIndication)
262 } else {
263 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onuIndication.GetOnuId()})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000264 return fmt.Errorf("invalidOperState: %s, %s", onuOperstate, dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530265 }
266 return nil
267}
268
Himani Chawla6d2ae152020-09-02 13:11:20 +0530269func (dh *deviceHandler) processInterAdapterTechProfileDownloadReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530270 msg *ic.InterAdapterMessage) error {
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000271
272 pDevEntry := dh.getOnuDeviceEntry(true)
273 if pDevEntry == nil {
274 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
275 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
276 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530277 if dh.pOnuTP == nil {
278 //should normally not happen ...
279 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
280 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000281 return fmt.Errorf("techProfile DLMsg request while onuTechProf instance not setup: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530282 }
283 if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
284 // I've seen cases for this request, where the device was already stopped
285 logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000286 return fmt.Errorf("device-unreachable: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530287 }
288
289 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{
293 "device-id": dh.deviceID, "error": err})
294 return err
295 }
296
297 // we have to lock access to TechProfile processing based on different messageType calls or
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000298 // even to fast subsequent calls of the same messageType as well as OnuKVStore processing due
299 // to possible concurrent access by flow processing
Himani Chawla26e555c2020-08-31 12:30:20 +0530300 dh.pOnuTP.lockTpProcMutex()
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000301 defer dh.pOnuTP.unlockTpProcMutex()
302 pDevEntry.lockOnuKVStoreMutex()
303 defer pDevEntry.unlockOnuKVStoreMutex()
304
305 if techProfMsg.UniId > 255 {
306 return fmt.Errorf(fmt.Sprintf("received UniId value exceeds range: %d, device-id: %s",
307 techProfMsg.UniId, dh.deviceID))
308 }
309 uniID := uint8(techProfMsg.UniId)
310
311 if bTpModify := pDevEntry.updateOnuUniTpPath(uniID, techProfMsg.Path); bTpModify {
Himani Chawla26e555c2020-08-31 12:30:20 +0530312 // if there has been some change for some uni TechProfilePath
313 //in order to allow concurrent calls to other dh instances we do not wait for execution here
314 //but doing so we can not indicate problems to the caller (who does what with that then?)
315 //by now we just assume straightforward successful execution
316 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
317 // possible problems to the caller later autonomously
318
319 // deadline context to ensure completion of background routines waited for
320 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +0530321 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Himani Chawla26e555c2020-08-31 12:30:20 +0530322 dctx, cancel := context.WithDeadline(context.Background(), deadline)
323
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000324 dh.pOnuTP.resetTpProcessingErrorIndication()
325 pDevEntry.resetKvProcessingErrorIndication()
326
Himani Chawla26e555c2020-08-31 12:30:20 +0530327 var wg sync.WaitGroup
328 wg.Add(2) // for the 2 go routines to finish
329 // attention: deadline completion check and wg.Done is to be done in both routines
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000330 go dh.pOnuTP.configureUniTp(dctx, uniID, techProfMsg.Path, &wg)
331 go pDevEntry.updateOnuKvStore(dctx, &wg)
332 dh.waitForCompletion(cancel, &wg) //wait for background process to finish
333
334 return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(), pDevEntry.getKvProcessingErrorIndication())
Himani Chawla26e555c2020-08-31 12:30:20 +0530335 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000336 // no change, nothing really to do - return success
Himani Chawla26e555c2020-08-31 12:30:20 +0530337 return nil
338}
339
Himani Chawla6d2ae152020-09-02 13:11:20 +0530340func (dh *deviceHandler) processInterAdapterDeleteGemPortReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530341 msg *ic.InterAdapterMessage) error {
342
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000343 pDevEntry := dh.getOnuDeviceEntry(true)
344 if pDevEntry == nil {
345 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
346 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
347 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530348 if dh.pOnuTP == nil {
349 //should normally not happen ...
350 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
351 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000352 return fmt.Errorf("techProfile DelGem request while onuTechProf instance not setup: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530353 }
354
355 msgBody := msg.GetBody()
356 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
357 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
358 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
359 "device-id": dh.deviceID, "error": err})
360 return err
361 }
362
363 //compare TECH_PROFILE_DOWNLOAD_REQUEST
364 dh.pOnuTP.lockTpProcMutex()
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000365 defer dh.pOnuTP.unlockTpProcMutex()
366 pDevEntry.lockOnuKVStoreMutex()
367 defer pDevEntry.unlockOnuKVStoreMutex()
Himani Chawla26e555c2020-08-31 12:30:20 +0530368
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000369 if delGemPortMsg.UniId > 255 {
370 return fmt.Errorf(fmt.Sprintf("received UniId value exceeds range: %d, device-id: %s",
371 delGemPortMsg.UniId, dh.deviceID))
372 }
373 uniID := uint8(delGemPortMsg.UniId)
Himani Chawla26e555c2020-08-31 12:30:20 +0530374
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000375 if bTpModify := pDevEntry.updateOnuUniTpPath(uniID, ""); bTpModify {
376 // deadline context to ensure completion of background routines waited for
Himani Chawlad96df182020-09-28 11:12:02 +0530377 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000378 dctx, cancel := context.WithDeadline(context.Background(), deadline)
379
380 dh.pOnuTP.resetTpProcessingErrorIndication()
381 pDevEntry.resetKvProcessingErrorIndication()
382
383 var wg sync.WaitGroup
384 wg.Add(2) // for the 2 go routines to finish
385 go pDevEntry.deleteTpResource(dctx, uniID, delGemPortMsg.TpPath,
386 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
387 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
388 go pDevEntry.updateOnuKvStore(dctx, &wg)
389 dh.waitForCompletion(cancel, &wg) //wait for background process to finish
390
391 return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(), pDevEntry.getKvProcessingErrorIndication())
392 }
393 return nil
Himani Chawla26e555c2020-08-31 12:30:20 +0530394}
395
Himani Chawla6d2ae152020-09-02 13:11:20 +0530396func (dh *deviceHandler) processInterAdapterDeleteTcontReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530397 msg *ic.InterAdapterMessage) error {
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000398
399 pDevEntry := dh.getOnuDeviceEntry(true)
400 if pDevEntry == nil {
401 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
402 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
403 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530404 if dh.pOnuTP == nil {
405 //should normally not happen ...
406 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
407 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000408 return fmt.Errorf("techProfile DelTcont request while onuTechProf instance not setup: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530409 }
410
411 msgBody := msg.GetBody()
412 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
413 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
414 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
415 "device-id": dh.deviceID, "error": err})
416 return err
417 }
418
419 //compare TECH_PROFILE_DOWNLOAD_REQUEST
420 dh.pOnuTP.lockTpProcMutex()
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000421 defer dh.pOnuTP.unlockTpProcMutex()
422 pDevEntry.lockOnuKVStoreMutex()
423 defer pDevEntry.unlockOnuKVStoreMutex()
424
425 if delTcontMsg.UniId > 255 {
426 return fmt.Errorf(fmt.Sprintf("received UniId value exceeds range: %d, device-id: %s",
427 delTcontMsg.UniId, dh.deviceID))
428 }
429 uniID := uint8(delTcontMsg.UniId)
430
431 if bTpModify := pDevEntry.updateOnuUniTpPath(uniID, ""); bTpModify {
Himani Chawla26e555c2020-08-31 12:30:20 +0530432 // deadline context to ensure completion of background routines waited for
Himani Chawlad96df182020-09-28 11:12:02 +0530433 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Himani Chawla26e555c2020-08-31 12:30:20 +0530434 dctx, cancel := context.WithDeadline(context.Background(), deadline)
435
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000436 dh.pOnuTP.resetTpProcessingErrorIndication()
437 pDevEntry.resetKvProcessingErrorIndication()
438
Himani Chawla26e555c2020-08-31 12:30:20 +0530439 var wg sync.WaitGroup
440 wg.Add(2) // for the 2 go routines to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000441 go pDevEntry.deleteTpResource(dctx, uniID, delTcontMsg.TpPath,
Himani Chawla26e555c2020-08-31 12:30:20 +0530442 cResourceTcont, delTcontMsg.AllocId, &wg)
443 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000444 go pDevEntry.updateOnuKvStore(dctx, &wg)
445 dh.waitForCompletion(cancel, &wg) //wait for background process to finish
446
447 return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(), pDevEntry.getKvProcessingErrorIndication())
Himani Chawla26e555c2020-08-31 12:30:20 +0530448 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530449 return nil
450}
451
Himani Chawla6d2ae152020-09-02 13:11:20 +0530452//processInterAdapterMessage sends the proxied messages to the target device
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000453// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
454// is meant, and then send the unmarshalled omci message to this onu
Himani Chawla6d2ae152020-09-02 13:11:20 +0530455func (dh *deviceHandler) processInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000456 msgID := msg.Header.Id
457 msgType := msg.Header.Type
458 fromTopic := msg.Header.FromTopic
459 toTopic := msg.Header.ToTopic
460 toDeviceID := msg.Header.ToDeviceId
461 proxyDeviceID := msg.Header.ProxyDeviceId
462 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
463 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
464
465 switch msgType {
466 case ic.InterAdapterMessageType_OMCI_REQUEST:
467 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530468 return dh.processInterAdapterOMCIReqMessage(msg)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000469 }
470 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
471 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530472 return dh.processInterAdapterONUIndReqMessage(msg)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000473 }
mpagenkoaf801632020-07-03 10:00:42 +0000474 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
475 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530476 return dh.processInterAdapterTechProfileDownloadReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000477 }
478 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
479 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530480 return dh.processInterAdapterDeleteGemPortReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000481
mpagenkoaf801632020-07-03 10:00:42 +0000482 }
483 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
484 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530485 return dh.processInterAdapterDeleteTcontReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000486 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000487 default:
488 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000489 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000490 "msgType": msg.Header.Type, "device-id": dh.deviceID})
491 return fmt.Errorf("inter-adapter-unhandled-type: %d, %s", msg.Header.Type, dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000492 }
493 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000494}
495
mpagenkodff5dda2020-08-28 11:52:01 +0000496//FlowUpdateIncremental removes and/or adds the flow changes on a given device
Himani Chawla6d2ae152020-09-02 13:11:20 +0530497func (dh *deviceHandler) FlowUpdateIncremental(apOfFlowChanges *openflow_13.FlowChanges,
mpagenkodff5dda2020-08-28 11:52:01 +0000498 apOfGroupChanges *openflow_13.FlowGroupChanges, apFlowMetaData *voltha.FlowMetadata) error {
Holger Hildebrandt8165eda2020-09-24 09:39:24 +0000499 logger.Debugw("FlowUpdateIncremental started", log.Fields{"deviceId": dh.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000500
501 //Remove flows
502 if apOfFlowChanges.ToRemove != nil {
503 for _, flowItem := range apOfFlowChanges.ToRemove.Items {
504 logger.Debugw("incremental flow item remove", log.Fields{"deviceId": dh.deviceID,
505 "Item": flowItem})
506 }
507 }
508 if apOfFlowChanges.ToAdd != nil {
509 for _, flowItem := range apOfFlowChanges.ToAdd.Items {
510 if flowItem.GetCookie() == 0 {
511 logger.Debugw("incremental flow add - no cookie - ignore", log.Fields{
512 "deviceId": dh.deviceID})
513 continue
514 }
515 flowInPort := flow.GetInPort(flowItem)
516 if flowInPort == uint32(of.OfpPortNo_OFPP_INVALID) {
517 logger.Errorw("flow inPort invalid", log.Fields{"deviceID": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000518 return fmt.Errorf("flow inPort invalid: %s", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +0000519 } else if flowInPort == dh.ponPortNumber {
520 //this is some downstream flow
521 logger.Debugw("incremental flow ignore downstream", log.Fields{
522 "deviceId": dh.deviceID, "inPort": flowInPort})
523 continue
524 } else {
525 // this is the relevant upstream flow
Himani Chawla6d2ae152020-09-02 13:11:20 +0530526 var loUniPort *onuUniPort
mpagenkodff5dda2020-08-28 11:52:01 +0000527 if uniPort, exist := dh.uniEntityMap[flowInPort]; exist {
528 loUniPort = uniPort
529 } else {
530 logger.Errorw("flow inPort not found in UniPorts",
531 log.Fields{"deviceID": dh.deviceID, "inPort": flowInPort})
532 return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
533 }
534 flowOutPort := flow.GetOutPort(flowItem)
535 logger.Debugw("incremental flow-add port indications", log.Fields{
536 "deviceId": dh.deviceID, "inPort": flowInPort, "outPort": flowOutPort,
537 "uniPortName": loUniPort.name})
538 err := dh.addFlowItemToUniPort(flowItem, loUniPort)
539 //abort processing in error case
540 if err != nil {
541 return err
542 }
543 }
544 }
545 }
546 return nil
547}
548
Himani Chawla6d2ae152020-09-02 13:11:20 +0530549//disableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530550func (dh *deviceHandler) disableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000551 logger.Debugw("disable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000552
mpagenko3af1f032020-06-10 08:53:41 +0000553 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
554 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
555 if dh.deviceReason != "omci-admin-lock" {
556 // disable UNI ports/ONU
557 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
558 // here the result of the processing is not checked (trusted in background) *****
559 if dh.pLockStateFsm == nil {
560 dh.createUniLockFsm(true, UniAdminStateDone)
561 } else { //LockStateFSM already init
Himani Chawla6d2ae152020-09-02 13:11:20 +0530562 dh.pLockStateFsm.setSuccessEvent(UniAdminStateDone)
mpagenko3af1f032020-06-10 08:53:41 +0000563 dh.runUniLockFsm(true)
564 }
Andrea Campanellaab7b6a52020-10-06 16:17:13 +0200565 dh.disableUniPortStateUpdate()
Holger Hildebrandt8165eda2020-09-24 09:39:24 +0000566 //VOL-3493/VOL-3495: postpone setting of deviceReason, conn- and operStatus until all omci-related communication regarding
567 //device disabling has finished successfully
ozgecanetsiafce57b12020-05-25 14:39:35 +0300568 }
569}
570
Himani Chawla6d2ae152020-09-02 13:11:20 +0530571//reEnableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530572func (dh *deviceHandler) reEnableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000573 logger.Debugw("reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000574
575 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandt8165eda2020-09-24 09:39:24 +0000576 logger.Debugw("call DeviceStateUpdate upon re-enable", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
577 "OperStatus": voltha.OperStatus_ACTIVE, "device-id": dh.deviceID})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300578 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
579 voltha.OperStatus_ACTIVE); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000580 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000581 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300582 }
583
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000584 // DeviceReason to update acc.to modified py code as per beginning of Sept 2020
585 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "onu-reenabled"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000586 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000587 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300588 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000589 dh.deviceReason = "onu-reenabled"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000590
591 // enable ONU/UNI ports
592 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
593 // here the result of the processing is not checked (trusted in background) *****
594 if dh.pUnlockStateFsm == nil {
595 dh.createUniLockFsm(false, UniAdminStateDone)
596 } else { //UnlockStateFSM already init
Himani Chawla6d2ae152020-09-02 13:11:20 +0530597 dh.pUnlockStateFsm.setSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000598 dh.runUniLockFsm(false)
599 }
Andrea Campanellaab7b6a52020-10-06 16:17:13 +0200600 //TODO this should be moved according to the discussion here
601 // https://gerrit.opencord.org/c/voltha-openonu-adapter-go/+/21066
602 dh.enableUniPortStateUpdate()
ozgecanetsiafce57b12020-05-25 14:39:35 +0300603}
604
Himani Chawla6d2ae152020-09-02 13:11:20 +0530605func (dh *deviceHandler) reconcileDeviceOnuInd() {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000606 logger.Debugw("reconciling - simulate onu indication", log.Fields{"device-id": dh.deviceID})
607
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000608 pDevEntry := dh.getOnuDeviceEntry(true)
609 if pDevEntry == nil {
610 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
611 return
612 }
613 if err := pDevEntry.restoreDataFromOnuKvStore(context.TODO()); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000614 logger.Errorw("reconciling - restoring OnuTp-data failed - abort", log.Fields{"err": err, "device-id": dh.deviceID})
615 dh.reconciling = false
616 return
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000617 }
Himani Chawla4d908332020-08-31 12:30:20 +0530618 var onuIndication oop.OnuIndication
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000619 onuIndication.IntfId = pDevEntry.sOnuPersistentData.PersIntfID
620 onuIndication.OnuId = pDevEntry.sOnuPersistentData.PersOnuID
621 onuIndication.OperState = pDevEntry.sOnuPersistentData.PersOperState
622 onuIndication.AdminState = pDevEntry.sOnuPersistentData.PersAdminState
Himani Chawla4d908332020-08-31 12:30:20 +0530623 _ = dh.createInterface(&onuIndication)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000624}
625
Himani Chawla6d2ae152020-09-02 13:11:20 +0530626func (dh *deviceHandler) reconcileDeviceTechProf() {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000627 logger.Debugw("reconciling - trigger tech profile config", log.Fields{"device-id": dh.deviceID})
628
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000629 pDevEntry := dh.getOnuDeviceEntry(true)
630 if pDevEntry == nil {
631 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
632 return
633 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000634
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000635 dh.pOnuTP.lockTpProcMutex()
636 defer dh.pOnuTP.unlockTpProcMutex()
637
638 for _, uniData := range pDevEntry.sOnuPersistentData.PersUniConfig {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000639 // deadline context to ensure completion of background routines waited for
640 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +0530641 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000642 dctx, cancel := context.WithDeadline(context.Background(), deadline)
643
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000644 dh.pOnuTP.resetTpProcessingErrorIndication()
645
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000646 var wg sync.WaitGroup
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000647 wg.Add(1) // for the 1 go routine to finish
648 go dh.pOnuTP.configureUniTp(dctx, uniData.PersUniID, uniData.PersTpPath, &wg)
649 dh.waitForCompletion(cancel, &wg) //wait for background process to finish
650
651 if err := dh.pOnuTP.getTpProcessingErrorIndication(); err != nil {
652 logger.Errorw(err.Error(), log.Fields{"device-id": dh.deviceID})
653 }
654 }
655}
656
657func (dh *deviceHandler) reconcileDeviceFlowConfig() {
658 logger.Debugw("reconciling - trigger flow config", log.Fields{"device-id": dh.deviceID})
659
660 pDevEntry := dh.getOnuDeviceEntry(true)
661 if pDevEntry == nil {
662 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000663 return
664 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000665 for _, uniData := range pDevEntry.sOnuPersistentData.PersUniConfig {
666 var uniPort *onuUniPort
667 var exist bool
668 uniNo := mkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(), uint32(uniData.PersUniID))
669 if uniPort, exist = dh.uniEntityMap[uniNo]; !exist {
670 logger.Errorw("onuUniPort data not found!", log.Fields{"uniNo": uniNo, "deviceID": dh.deviceID})
671 return
672 }
673 for _, flowData := range uniData.PersFlowParams {
674 if _, exist = dh.UniVlanConfigFsmMap[uniData.PersUniID]; exist {
675 if err := dh.UniVlanConfigFsmMap[uniData.PersUniID].SetUniFlowParams(flowData.TpID, uint16(flowData.MatchVid),
676 uint16(flowData.SetVid), uint8(flowData.SetPcp)); err != nil {
677 logger.Errorw(err.Error(), log.Fields{"device-id": dh.deviceID})
678 }
679
680 } else {
681 if err := dh.createVlanFilterFsm(uniPort, flowData.TpID, uint16(flowData.MatchVid), uint16(flowData.SetVid),
682 uint8(flowData.SetPcp), OmciVlanFilterDone); err != nil {
683 logger.Errorw(err.Error(), log.Fields{"device-id": dh.deviceID})
684 }
685 }
686 }
687 }
688}
689
690func (dh *deviceHandler) reconcileMetrics() {
691 logger.Debugw("reconciling - trigger metrics - to be implemented in scope of VOL-3324!", log.Fields{"device-id": dh.deviceID})
692
693 //TODO: reset of reconciling-flag has always to be done in the last reconcile*() function
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000694 dh.reconciling = false
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000695}
696
Himani Chawla6d2ae152020-09-02 13:11:20 +0530697func (dh *deviceHandler) deleteDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000698 logger.Debugw("delete-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000699
700 pDevEntry := dh.getOnuDeviceEntry(true)
701 if pDevEntry == nil {
702 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
703 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000704 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000705 pDevEntry.lockOnuKVStoreMutex()
706 defer pDevEntry.unlockOnuKVStoreMutex()
707
708 // deadline context to ensure completion of background routines waited for
709 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +0530710 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000711 dctx, cancel := context.WithDeadline(context.Background(), deadline)
712
713 pDevEntry.resetKvProcessingErrorIndication()
714
715 var wg sync.WaitGroup
716 wg.Add(1) // for the 1 go routine to finish
717 go pDevEntry.deleteDataFromOnuKvStore(dctx, &wg)
718 dh.waitForCompletion(cancel, &wg) //wait for background process to finish
719
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000720 // TODO: further actions - stop metrics and FSMs, remove device ...
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000721 return pDevEntry.getKvProcessingErrorIndication()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000722}
723
Himani Chawla6d2ae152020-09-02 13:11:20 +0530724func (dh *deviceHandler) rebootDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000725 logger.Debugw("reboot-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300726 if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
divyadesai4d299552020-08-18 07:13:49 +0000727 logger.Errorw("device-unreachable", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000728 return fmt.Errorf("device-unreachable: %s, %s", dh.deviceID, device.SerialNumber)
ozgecanetsiae11479f2020-07-06 09:44:47 +0300729 }
Himani Chawla6d2ae152020-09-02 13:11:20 +0530730 if err := dh.pOnuOmciDevice.reboot(context.TODO()); err != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530731 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
732 logger.Errorw("error-rebooting-device", log.Fields{"device-id": dh.deviceID, "error": err})
733 return err
734 }
Holger Hildebrandt8165eda2020-09-24 09:39:24 +0000735 logger.Debugw("call DeviceStateUpdate upon reboot", log.Fields{"ConnectStatus": voltha.ConnectStatus_UNREACHABLE,
736 "OperStatus": voltha.OperStatus_DISCOVERED, "device-id": dh.deviceID})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300737 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
738 voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000739 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000740 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300741 return err
742 }
743 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting-onu"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000744 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000745 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300746 return err
747 }
748 dh.deviceReason = "rebooting-onu"
749 return nil
750}
751
Himani Chawla6d2ae152020-09-02 13:11:20 +0530752// deviceHandler methods that implement the adapters interface requests## end #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000753// #####################################################################################
754
755// ################ to be updated acc. needs of ONU Device ########################
Himani Chawla6d2ae152020-09-02 13:11:20 +0530756// deviceHandler StateMachine related state transition methods ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000757
Himani Chawla6d2ae152020-09-02 13:11:20 +0530758func (dh *deviceHandler) logStateChange(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000759 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})
760}
761
762// doStateInit provides the device update to the core
Himani Chawla6d2ae152020-09-02 13:11:20 +0530763func (dh *deviceHandler) doStateInit(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000764
765 logger.Debug("doStateInit-started")
766 var err error
767
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000768 // populate what we know. rest comes later after mib sync
769 dh.device.Root = false
770 dh.device.Vendor = "OpenONU"
771 dh.device.Model = "go"
772 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000773 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000774
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000775 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000776
777 if !dh.reconciling {
Himani Chawla4d908332020-08-31 12:30:20 +0530778 _ = dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000779 } else {
780 logger.Debugw("reconciling - don't notify core about DeviceUpdate",
781 log.Fields{"device-id": dh.deviceID})
782 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000783
Himani Chawla4d908332020-08-31 12:30:20 +0530784 dh.parentID = dh.device.ParentId
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000785 dh.ponPortNumber = dh.device.ParentPortNo
786
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000787 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
788 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
789 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
divyadesai4d299552020-08-18 07:13:49 +0000790 logger.Debugw("device-updated", log.Fields{"device-id": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000791 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Himani Chawla4d908332020-08-31 12:30:20 +0530792 "ParentId": dh.parentID, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000793
794 /*
795 self._pon = PonPort.create(self, self._pon_port_number)
796 self._pon.add_peer(self.parent_id, self._pon_port_number)
797 self.logger.debug('adding-pon-port-to-agent',
798 type=self._pon.get_port().type,
799 admin_state=self._pon.get_port().admin_state,
800 oper_status=self._pon.get_port().oper_status,
801 )
802 */
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000803 if !dh.reconciling {
804 logger.Debugw("adding-pon-port", log.Fields{"deviceID": dh.deviceID, "ponPortNo": dh.ponPortNumber})
805 var ponPortNo uint32 = 1
806 if dh.ponPortNumber != 0 {
807 ponPortNo = dh.ponPortNumber
808 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000809
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000810 pPonPort := &voltha.Port{
811 PortNo: ponPortNo,
812 Label: fmt.Sprintf("pon-%d", ponPortNo),
813 Type: voltha.Port_PON_ONU,
814 OperStatus: voltha.OperStatus_ACTIVE,
Himani Chawla4d908332020-08-31 12:30:20 +0530815 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentID, // Peer device is OLT
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000816 PortNo: ponPortNo}}, // Peer port is parent's port number
817 }
818 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
819 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
820 e.Cancel(err)
821 return
822 }
823 } else {
824 logger.Debugw("reconciling - pon-port already added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000825 }
826 logger.Debug("doStateInit-done")
827}
828
829// postInit setups the DeviceEntry for the conerned device
Himani Chawla6d2ae152020-09-02 13:11:20 +0530830func (dh *deviceHandler) postInit(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000831
832 logger.Debug("postInit-started")
833 var err error
834 /*
835 dh.Client = oop.NewOpenoltClient(dh.clientCon)
836 dh.pTransitionMap.Handle(ctx, GrpcConnected)
837 return nil
838 */
Himani Chawla6d2ae152020-09-02 13:11:20 +0530839 if err = dh.addOnuDeviceEntry(context.TODO()); err != nil {
840 logger.Fatalf("Device FSM: addOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000841 e.Cancel(err)
842 return
843 }
844
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000845 if dh.reconciling {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530846 go dh.reconcileDeviceOnuInd()
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000847 // reconcilement will be continued after mib download is done
848 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000849 /*
850 ############################################################################
851 # Setup Alarm handler
852 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
853 device.serial_number)
854 ############################################################################
855 # Setup PM configuration for this device
856 # Pass in ONU specific options
857 kwargs = {
858 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
859 'heartbeat': self.heartbeat,
860 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
861 }
862 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
863 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
864 self.logical_device_id, device.serial_number,
865 grouped=True, freq_override=False, **kwargs)
866 pm_config = self._pm_metrics.make_proto()
867 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
868 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
869 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
870
871 # Note, ONU ID and UNI intf set in add_uni_port method
872 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
873 ani_ports=[self._pon])
874
875 # Code to Run OMCI Test Action
876 kwargs_omci_test_action = {
877 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
878 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
879 }
880 serial_number = device.serial_number
881 self._test_request = OmciTestRequest(self.core_proxy,
882 self.omci_agent, self.device_id,
883 AniG, serial_number,
884 self.logical_device_id,
885 exclusive=False,
886 **kwargs_omci_test_action)
887
888 self.enabled = True
889 else:
890 self.logger.info('onu-already-activated')
891 */
892 logger.Debug("postInit-done")
893}
894
895// doStateConnected get the device info and update to voltha core
896// for comparison of the original method (not that easy to uncomment): compare here:
897// voltha-openolt-adapter/adaptercore/device_handler.go
898// -> this one obviously initiates all communication interfaces of the device ...?
Himani Chawla6d2ae152020-09-02 13:11:20 +0530899func (dh *deviceHandler) doStateConnected(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000900
901 logger.Debug("doStateConnected-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530902 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000903 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000904 logger.Debug("doStateConnected-done")
905}
906
907// doStateUp handle the onu up indication and update to voltha core
Himani Chawla6d2ae152020-09-02 13:11:20 +0530908func (dh *deviceHandler) doStateUp(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000909
910 logger.Debug("doStateUp-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530911 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000912 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000913 logger.Debug("doStateUp-done")
914
915 /*
916 // Synchronous call to update device state - this method is run in its own go routine
917 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
918 voltha.OperStatus_ACTIVE); err != nil {
919 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
920 return err
921 }
922 return nil
923 */
924}
925
926// doStateDown handle the onu down indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530927func (dh *deviceHandler) doStateDown(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000928
929 logger.Debug("doStateDown-started")
930 var err error
931
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000932 device := dh.device
933 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000934 /*TODO: needs to handle error scenarios */
Andrea Campanella6515c582020-10-05 11:25:00 +0200935 logger.Errorw("Failed to fetch handler device", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000936 e.Cancel(err)
937 return
938 }
939
940 cloned := proto.Clone(device).(*voltha.Device)
941 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
942 /*
943 // Update the all ports state on that device to disable
944 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
945 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
946 return er
947 }
948
949 //Update the device oper state and connection status
950 cloned.OperStatus = voltha.OperStatus_UNKNOWN
951 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
952 dh.device = cloned
953
954 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
955 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
956 return er
957 }
958
959 //get the child device for the parent device
960 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
961 if err != nil {
962 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
963 return err
964 }
965 for _, onuDevice := range onuDevices.Items {
966
967 // Update onu state as down in onu adapter
968 onuInd := oop.OnuIndication{}
969 onuInd.OperState = "down"
970 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
971 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
972 if er != nil {
973 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
974 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
975 //Do not return here and continue to process other ONUs
976 }
977 }
978 // * Discovered ONUs entries need to be cleared , since after OLT
979 // is up, it starts sending discovery indications again* /
980 dh.discOnus = sync.Map{}
981 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
982 return nil
983 */
Himani Chawla4d908332020-08-31 12:30:20 +0530984 err = errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000985 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000986 logger.Debug("doStateDown-done")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000987}
988
Himani Chawla6d2ae152020-09-02 13:11:20 +0530989// deviceHandler StateMachine related state transition methods ##### end #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000990// #################################################################################
991
992// ###################################################
Himani Chawla6d2ae152020-09-02 13:11:20 +0530993// deviceHandler utility methods ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000994
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000995//getOnuDeviceEntry gets the ONU device entry and may wait until its value is defined
Himani Chawla6d2ae152020-09-02 13:11:20 +0530996func (dh *deviceHandler) getOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
mpagenko3af1f032020-06-10 08:53:41 +0000997 dh.lockDevice.RLock()
998 pOnuDeviceEntry := dh.pOnuOmciDevice
999 if aWait && pOnuDeviceEntry == nil {
1000 //keep the read sema short to allow for subsequent write
1001 dh.lockDevice.RUnlock()
divyadesai4d299552020-08-18 07:13:49 +00001002 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001003 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
1004 // so it might be needed to wait here for that event with some timeout
1005 select {
1006 case <-time.After(60 * time.Second): //timer may be discussed ...
divyadesai4d299552020-08-18 07:13:49 +00001007 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001008 return nil
1009 case <-dh.deviceEntrySet:
divyadesai4d299552020-08-18 07:13:49 +00001010 logger.Debugw("devicEntry ready now - continue", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001011 // if written now, we can return the written value without sema
1012 return dh.pOnuOmciDevice
1013 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001014 }
mpagenko3af1f032020-06-10 08:53:41 +00001015 dh.lockDevice.RUnlock()
1016 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001017}
1018
Himani Chawla6d2ae152020-09-02 13:11:20 +05301019//setOnuDeviceEntry sets the ONU device entry within the handler
1020func (dh *deviceHandler) setOnuDeviceEntry(
1021 apDeviceEntry *OnuDeviceEntry, apOnuTp *onuUniTechProf) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001022 dh.lockDevice.Lock()
1023 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +00001024 dh.pOnuOmciDevice = apDeviceEntry
1025 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001026}
1027
Himani Chawla6d2ae152020-09-02 13:11:20 +05301028//addOnuDeviceEntry creates a new ONU device or returns the existing
1029func (dh *deviceHandler) addOnuDeviceEntry(ctx context.Context) error {
divyadesai4d299552020-08-18 07:13:49 +00001030 logger.Debugw("adding-deviceEntry", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001031
Himani Chawla6d2ae152020-09-02 13:11:20 +05301032 deviceEntry := dh.getOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001033 if deviceEntry == nil {
1034 /* costum_me_map in python code seems always to be None,
1035 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
1036 /* also no 'clock' argument - usage open ...*/
1037 /* and no alarm_db yet (oo.alarm_db) */
Himani Chawla6d2ae152020-09-02 13:11:20 +05301038 deviceEntry = newOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
mpagenkoaf801632020-07-03 10:00:42 +00001039 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001040 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001041 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
Himani Chawla6d2ae152020-09-02 13:11:20 +05301042 onuTechProfProc := newOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001043 //error treatment possible //TODO!!!
Himani Chawla6d2ae152020-09-02 13:11:20 +05301044 dh.setOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +00001045 // fire deviceEntry ready event to spread to possibly waiting processing
1046 dh.deviceEntrySet <- true
divyadesai4d299552020-08-18 07:13:49 +00001047 logger.Infow("onuDeviceEntry-added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001048 } else {
divyadesai4d299552020-08-18 07:13:49 +00001049 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001050 }
1051 // might be updated with some error handling !!!
1052 return nil
1053}
1054
1055// doStateInit provides the device update to the core
Himani Chawla6d2ae152020-09-02 13:11:20 +05301056func (dh *deviceHandler) createInterface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001057 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
1058 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
1059
1060 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001061
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001062 if !dh.reconciling {
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001063 logger.Debugw("call DeviceStateUpdate upon create interface", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
1064 "OperStatus": voltha.OperStatus_ACTIVATING, "device-id": dh.deviceID})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001065 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1066 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
1067 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1068 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1069 }
1070 } else {
1071 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVATING",
1072 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001073 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001074 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
1075 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
1076 // 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 +00001077 // 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 +00001078 // so let's just try to keep it simple ...
1079 /*
1080 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
1081 if err != nil || device == nil {
1082 //TODO: needs to handle error scenarios
1083 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
1084 return errors.New("Voltha Device not found")
1085 }
1086 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001087
Himani Chawla6d2ae152020-09-02 13:11:20 +05301088 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenko3af1f032020-06-10 08:53:41 +00001089 if pDevEntry != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +05301090 if err := pDevEntry.start(context.TODO()); err != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301091 return err
1092 }
mpagenko3af1f032020-06-10 08:53:41 +00001093 } else {
divyadesai4d299552020-08-18 07:13:49 +00001094 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001095 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
mpagenko3af1f032020-06-10 08:53:41 +00001096 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001097 if !dh.reconciling {
1098 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
1099 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1100 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"device-id": dh.deviceID, "error": err})
1101 }
1102 } else {
1103 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to starting-openomci",
1104 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001105 }
mpagenko3af1f032020-06-10 08:53:41 +00001106 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001107
1108 /* this might be a good time for Omci Verify message? */
1109 verifyExec := make(chan bool)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301110 omciVerify := newOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +00001111 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001112 true, true) //eclusive and allowFailure (anyway not yet checked)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301113 omciVerify.performOmciTest(context.TODO(), verifyExec)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001114
1115 /* give the handler some time here to wait for the OMCi verification result
1116 after Timeout start and try MibUpload FSM anyway
1117 (to prevent stopping on just not supported OMCI verification from ONU) */
1118 select {
1119 case <-time.After(2 * time.Second):
1120 logger.Warn("omci start-verification timed out (continue normal)")
1121 case testresult := <-verifyExec:
1122 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
1123 }
1124
1125 /* In py code it looks earlier (on activate ..)
1126 # Code to Run OMCI Test Action
1127 kwargs_omci_test_action = {
1128 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
1129 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
1130 }
1131 serial_number = device.serial_number
1132 self._test_request = OmciTestRequest(self.core_proxy,
1133 self.omci_agent, self.device_id,
1134 AniG, serial_number,
1135 self.logical_device_id,
1136 exclusive=False,
1137 **kwargs_omci_test_action)
1138 ...
1139 # Start test requests after a brief pause
1140 if not self._test_request_started:
1141 self._test_request_started = True
1142 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
1143 reactor.callLater(tststart, self._test_request.start_collector)
1144
1145 */
1146 /* which is then: in omci_test_request.py : */
1147 /*
1148 def start_collector(self, callback=None):
1149 """
1150 Start the collection loop for an adapter if the frequency > 0
1151
1152 :param callback: (callable) Function to call to collect PM data
1153 """
1154 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
1155 if callback is None:
1156 callback = self.perform_test_omci
1157
1158 if self.lc is None:
1159 self.lc = LoopingCall(callback)
1160
1161 if self.default_freq > 0:
1162 self.lc.start(interval=self.default_freq / 10)
1163
1164 def perform_test_omci(self):
1165 """
1166 Perform the initial test request
1167 """
1168 ani_g_entities = self._device.configuration.ani_g_entities
1169 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
1170 is not None else None
1171 self._entity_id = ani_g_entities_ids[0]
1172 self.logger.info('perform-test', entity_class=self._entity_class,
1173 entity_id=self._entity_id)
1174 try:
1175 frame = MEFrame(self._entity_class, self._entity_id, []).test()
1176 result = yield self._device.omci_cc.send(frame)
1177 if not result.fields['omci_message'].fields['success_code']:
1178 self.logger.info('Self-Test Submitted Successfully',
1179 code=result.fields[
1180 'omci_message'].fields['success_code'])
1181 else:
1182 raise TestFailure('Test Failure: {}'.format(
1183 result.fields['omci_message'].fields['success_code']))
1184 except TimeoutError as e:
1185 self.deferred.errback(failure.Failure(e))
1186
1187 except Exception as e:
1188 self.logger.exception('perform-test-Error', e=e,
1189 class_id=self._entity_class,
1190 entity_id=self._entity_id)
1191 self.deferred.errback(failure.Failure(e))
1192
1193 */
1194
1195 // PM related heartbeat??? !!!TODO....
1196 //self._heartbeat.enabled = True
1197
mpagenko1cc3cb42020-07-27 15:24:38 +00001198 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
1199 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
1200 * as further OltAdapter processing may rely on the deviceReason event 'MibUploadDone' as a result of the FSM processing
Himani Chawla4d908332020-08-31 12:30:20 +05301201 * otherwise some processing synchronization would be required - cmp. e.g TechProfile processing
mpagenko1cc3cb42020-07-27 15:24:38 +00001202 */
1203 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +00001204 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001205 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001206 if pMibUlFsm.Is(ulStDisabled) {
1207 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Andrea Campanella6515c582020-10-05 11:25:00 +02001208 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"deviceId": dh.deviceID, "err": err})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001209 return fmt.Errorf("can't go to state starting: %s", dh.deviceID)
Himani Chawla4d908332020-08-31 12:30:20 +05301210 }
1211 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1212 //Determine ONU status and start/re-start MIB Synchronization tasks
1213 //Determine if this ONU has ever synchronized
1214 if true { //TODO: insert valid check
1215 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
Andrea Campanella6515c582020-10-05 11:25:00 +02001216 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"deviceId": dh.deviceID, "err": err})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001217 return fmt.Errorf("can't go to state resetting_mib: %s", dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001218 }
Himani Chawla4d908332020-08-31 12:30:20 +05301219 } else {
1220 if err := pMibUlFsm.Event(ulEvExamineMds); err != nil {
Andrea Campanella6515c582020-10-05 11:25:00 +02001221 logger.Errorw("MibSyncFsm: Can't go to state examine_mds", log.Fields{"deviceId": dh.deviceID, "err": err})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001222 return fmt.Errorf("can't go to examine_mds: %s", dh.deviceID)
Himani Chawla4d908332020-08-31 12:30:20 +05301223 }
1224 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1225 //Examine the MIB Data Sync
1226 // callbacks to be handled:
1227 // Event(ulEvSuccess)
1228 // Event(ulEvTimeout)
1229 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001230 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001231 } else {
Andrea Campanella6515c582020-10-05 11:25:00 +02001232 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current()),
1233 "deviceId": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001234 return fmt.Errorf("wrong state of MibSyncFsm: %s", dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001235 }
1236 } else {
divyadesai4d299552020-08-18 07:13:49 +00001237 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001238 return fmt.Errorf("can't execute MibSync: %s", dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001239 }
1240 return nil
1241}
1242
Himani Chawla6d2ae152020-09-02 13:11:20 +05301243func (dh *deviceHandler) updateInterface(onuind *oop.OnuIndication) error {
mpagenko3af1f032020-06-10 08:53:41 +00001244 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
1245 if dh.deviceReason != "stopping-openomci" {
divyadesai4d299552020-08-18 07:13:49 +00001246 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001247 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
Himani Chawla6d2ae152020-09-02 13:11:20 +05301248 pDevEntry := dh.getOnuDeviceEntry(false)
mpagenko3af1f032020-06-10 08:53:41 +00001249 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001250 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001251 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
mpagenko3af1f032020-06-10 08:53:41 +00001252 }
1253
1254 switch dh.deviceReason {
1255 case "starting-openomci":
1256 { //MIBSync FSM may run
1257 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
1258 if pMibUlFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301259 _ = pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +00001260 }
1261 }
1262 case "discovery-mibsync-complete":
1263 { //MibDownload may run
1264 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1265 if pMibDlFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301266 _ = pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001267 }
1268 }
1269 default:
mpagenko3dbcdd22020-07-22 07:38:45 +00001270 {
1271 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +00001272 if dh.pUnlockStateFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301273 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001274 }
1275 if dh.pLockStateFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301276 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001277 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001278 //techProfile related PonAniConfigFsm FSM may be active
1279 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
1280 if dh.pOnuTP.pAniConfigFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301281 _ = dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +00001282 }
mpagenkodff5dda2020-08-28 11:52:01 +00001283 for _, uniPort := range dh.uniEntityMap {
1284 //reset the TechProfileConfig Done state for all (active) UNI's
Himani Chawla26e555c2020-08-31 12:30:20 +05301285 dh.pOnuTP.setConfigDone(uniPort.uniID, false)
1286 // reset the possibly existing VlanConfigFsm
1287 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[uniPort.uniID]; exist {
mpagenkodff5dda2020-08-28 11:52:01 +00001288 //VlanFilterFsm exists and was already started
1289 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1290 if pVlanFilterStatemachine != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301291 _ = pVlanFilterStatemachine.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001292 }
1293 }
1294 }
mpagenko3af1f032020-06-10 08:53:41 +00001295 }
1296 //TODO!!! care about PM/Alarm processing once started
1297 }
1298 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
Himani Chawla4d908332020-08-31 12:30:20 +05301299 // (mainly the still separate 'Event states')
mpagenko3af1f032020-06-10 08:53:41 +00001300 // so it is questionable, how this is resolved after some possible re-enable
1301 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1302
1303 //stop/remove(?) the device entry
Himani Chawla6d2ae152020-09-02 13:11:20 +05301304 _ = pDevEntry.stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
mpagenko3af1f032020-06-10 08:53:41 +00001305
1306 //TODO!!! remove existing traffic profiles
1307 /* from py code, if TP's exist, remove them - not yet implemented
1308 self._tp = dict()
1309 # Let TP download happen again
1310 for uni_id in self._tp_service_specific_task:
1311 self._tp_service_specific_task[uni_id].clear()
1312 for uni_id in self._tech_profile_download_done:
1313 self._tech_profile_download_done[uni_id].clear()
1314 */
1315
1316 dh.disableUniPortStateUpdate()
1317
1318 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001319 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001320 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
divyadesai4d299552020-08-18 07:13:49 +00001321 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001322 // abort: system behavior is just unstable ...
1323 return err
1324 }
1325 dh.deviceReason = "stopping-openomci"
1326
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001327 logger.Debugw("call DeviceStateUpdate upon update interface", log.Fields{"ConnectStatus": voltha.ConnectStatus_UNREACHABLE,
1328 "OperStatus": voltha.OperStatus_DISCOVERED, "device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001329 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1330 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001331 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001332 logger.Errorw("error-updating-device-state unreachable-discovered",
divyadesai4d299552020-08-18 07:13:49 +00001333 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001334 // abort: system behavior is just unstable ...
1335 return err
1336 }
1337 } else {
divyadesai4d299552020-08-18 07:13:49 +00001338 logger.Debugw("updateInterface - device already stopped", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001339 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001340 return nil
1341}
1342
Himani Chawla6d2ae152020-09-02 13:11:20 +05301343func (dh *deviceHandler) processMibDatabaseSyncEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301344 logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
1345 if !dh.reconciling {
1346 //initiate DevStateUpdate
1347 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1348 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1349 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1350 "device-id": dh.deviceID, "error": err})
1351 } else {
1352 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
1353 }
1354 } else {
1355 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
1356 log.Fields{"device-id": dh.deviceID})
1357 }
1358 //set internal state anyway - as it was done
1359 dh.deviceReason = "discovery-mibsync-complete"
1360
1361 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301362 pDevEntry := dh.getOnuDeviceEntry(false)
1363 if unigInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301364 for _, mgmtEntityID := range unigInstKeys {
1365 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1366 "device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301367 dh.addUniPort(mgmtEntityID, i, uniPPTP)
Himani Chawla26e555c2020-08-31 12:30:20 +05301368 i++
1369 }
1370 } else {
1371 logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
1372 }
Himani Chawla6d2ae152020-09-02 13:11:20 +05301373 if veipInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301374 for _, mgmtEntityID := range veipInstKeys {
1375 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1376 "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301377 dh.addUniPort(mgmtEntityID, i, uniVEIP)
Himani Chawla26e555c2020-08-31 12:30:20 +05301378 i++
1379 }
1380 } else {
1381 logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
1382 }
1383 if i == 0 {
1384 logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
1385 }
1386
1387 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1388 * left the code here as comment in case such processing should prove needed unexpectedly
1389 // Init Uni Ports to Admin locked state
1390 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1391 // *** should generate UniLockStateDone event *****
1392 if dh.pLockStateFsm == nil {
1393 dh.createUniLockFsm(true, UniLockStateDone)
1394 } else { //LockStateFSM already init
1395 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1396 dh.runUniLockFsm(true)
1397 }
1398 }
1399 case UniLockStateDone:
1400 {
1401 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
1402 * lockState processing commented out
1403 */
1404 /* Mib download procedure -
1405 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1406 */
1407 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1408 if pMibDlFsm != nil {
1409 if pMibDlFsm.Is(dlStDisabled) {
1410 if err := pMibDlFsm.Event(dlEvStart); err != nil {
Andrea Campanella6515c582020-10-05 11:25:00 +02001411 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"deviceId": dh.deviceID, "err": err})
Himani Chawla26e555c2020-08-31 12:30:20 +05301412 // maybe try a FSM reset and then again ... - TODO!!!
1413 } else {
1414 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1415 // maybe use more specific states here for the specific download steps ...
1416 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
Andrea Campanella6515c582020-10-05 11:25:00 +02001417 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"deviceId": dh.deviceID, "err": err})
Himani Chawla26e555c2020-08-31 12:30:20 +05301418 } else {
1419 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1420 //Begin MIB data download (running autonomously)
1421 }
1422 }
1423 } else {
Andrea Campanella6515c582020-10-05 11:25:00 +02001424 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current()),
1425 "deviceId": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301426 // maybe try a FSM reset and then again ... - TODO!!!
1427 }
1428 /***** Mib download started */
1429 } else {
1430 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
1431 }
1432}
1433
Himani Chawla6d2ae152020-09-02 13:11:20 +05301434func (dh *deviceHandler) processMibDownloadDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301435 logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
1436 //initiate DevStateUpdate
1437 if !dh.reconciling {
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001438 logger.Debugw("call DeviceStateUpdate upon mib-download done", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
1439 "OperStatus": voltha.OperStatus_ACTIVE, "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301440 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1441 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1442 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1443 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1444 } else {
1445 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
1446 }
1447 } else {
1448 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
1449 log.Fields{"device-id": dh.deviceID})
1450 }
1451 if !dh.reconciling {
1452 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1453 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1454 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1455 log.Fields{"device-id": dh.deviceID, "error": err})
1456 } else {
1457 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
1458 }
1459 } else {
1460 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
1461 log.Fields{"device-id": dh.deviceID})
1462 }
1463 //set internal state anyway - as it was done
1464 dh.deviceReason = "initial-mib-downloaded"
1465 // *** should generate UniUnlockStateDone event *****
1466 if dh.pUnlockStateFsm == nil {
1467 dh.createUniLockFsm(false, UniUnlockStateDone)
1468 } else { //UnlockStateFSM already init
Himani Chawla6d2ae152020-09-02 13:11:20 +05301469 dh.pUnlockStateFsm.setSuccessEvent(UniUnlockStateDone)
Himani Chawla26e555c2020-08-31 12:30:20 +05301470 dh.runUniLockFsm(false)
1471 }
1472}
1473
Himani Chawla6d2ae152020-09-02 13:11:20 +05301474func (dh *deviceHandler) processUniUnlockStateDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301475 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
1476
1477 if !dh.reconciling {
1478 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
1479 raisedTs := time.Now().UnixNano()
1480 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1481 } else {
1482 logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
1483 log.Fields{"device-id": dh.deviceID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301484 go dh.reconcileDeviceTechProf()
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001485 // reconcilement will be continued after ani config is done
Himani Chawla26e555c2020-08-31 12:30:20 +05301486 }
1487}
1488
Himani Chawla6d2ae152020-09-02 13:11:20 +05301489func (dh *deviceHandler) processOmciAniConfigDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301490 logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
1491 // attention: the device reason update is done based on ONU-UNI-Port related activity
1492 // - which may cause some inconsistency
1493 if dh.deviceReason != "tech-profile-config-download-success" {
1494 // which may be the case from some previous actvity on another UNI Port of the ONU
1495 if !dh.reconciling {
1496 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1497 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1498 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1499 log.Fields{"device-id": dh.deviceID, "error": err})
1500 } else {
1501 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1502 log.Fields{"device-id": dh.deviceID})
1503 }
1504 } else {
1505 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
1506 log.Fields{"device-id": dh.deviceID})
1507 }
1508 //set internal state anyway - as it was done
1509 dh.deviceReason = "tech-profile-config-download-success"
1510 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001511 if dh.reconciling {
1512 go dh.reconcileDeviceFlowConfig()
1513 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301514}
1515
Himani Chawla6d2ae152020-09-02 13:11:20 +05301516func (dh *deviceHandler) processOmciVlanFilterDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301517 logger.Debugw("OmciVlanFilterDone event received",
1518 log.Fields{"device-id": dh.deviceID})
1519 // attention: the device reason update is done based on ONU-UNI-Port related activity
1520 // - which may cause some inconsistency
1521 // yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
1522
1523 if dh.deviceReason != "omci-flows-pushed" {
1524 // which may be the case from some previous actvity on another UNI Port of the ONU
1525 // or even some previous flow add activity on the same port
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001526 if !dh.reconciling {
1527 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
1528 logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
1529 log.Fields{"device-id": dh.deviceID, "error": err})
1530 } else {
1531 logger.Infow("updated dev reason to ''omci-flows-pushed'",
1532 log.Fields{"device-id": dh.deviceID})
1533 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301534 } else {
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001535 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to omci-flows-pushed",
Himani Chawla26e555c2020-08-31 12:30:20 +05301536 log.Fields{"device-id": dh.deviceID})
1537 }
1538 //set internal state anyway - as it was done
1539 dh.deviceReason = "omci-flows-pushed"
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001540
1541 if dh.reconciling {
1542 go dh.reconcileMetrics()
1543 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301544 }
1545}
1546
Himani Chawla6d2ae152020-09-02 13:11:20 +05301547//deviceProcStatusUpdate evaluates possible processing events and initiates according next activities
1548func (dh *deviceHandler) deviceProcStatusUpdate(devEvent OnuDeviceEvent) {
Himani Chawla4d908332020-08-31 12:30:20 +05301549 switch devEvent {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001550 case MibDatabaseSync:
1551 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301552 dh.processMibDatabaseSyncEvent(devEvent)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001553 }
1554 case MibDownloadDone:
1555 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301556 dh.processMibDownloadDoneEvent(devEvent)
1557
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001558 }
1559 case UniUnlockStateDone:
1560 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301561 dh.processUniUnlockStateDoneEvent(devEvent)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001562
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001563 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001564 case OmciAniConfigDone:
1565 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301566 dh.processOmciAniConfigDoneEvent(devEvent)
1567
mpagenko3dbcdd22020-07-22 07:38:45 +00001568 }
mpagenkodff5dda2020-08-28 11:52:01 +00001569 case OmciVlanFilterDone:
1570 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301571 dh.processOmciVlanFilterDoneEvent(devEvent)
mpagenkodff5dda2020-08-28 11:52:01 +00001572
mpagenkodff5dda2020-08-28 11:52:01 +00001573 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001574 default:
1575 {
Andrea Campanellaab7b6a52020-10-06 16:17:13 +02001576 logger.Debugw("unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": devEvent})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001577 }
1578 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001579}
1580
Himani Chawla6d2ae152020-09-02 13:11:20 +05301581func (dh *deviceHandler) addUniPort(aUniInstNo uint16, aUniID uint8, aPortType uniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001582 // parameters are IntfId, OnuId, uniId
Himani Chawla6d2ae152020-09-02 13:11:20 +05301583 uniNo := mkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
Himani Chawla4d908332020-08-31 12:30:20 +05301584 uint32(aUniID))
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001585 if _, present := dh.uniEntityMap[uniNo]; present {
Himani Chawla4d908332020-08-31 12:30:20 +05301586 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001587 } else {
Himani Chawla4d908332020-08-31 12:30:20 +05301588 //with arguments aUniID, a_portNo, aPortType
Himani Chawla6d2ae152020-09-02 13:11:20 +05301589 pUniPort := newOnuUniPort(aUniID, uniNo, aUniInstNo, aPortType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001590 if pUniPort == nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301591 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001592 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001593 //store UniPort with the System-PortNumber key
1594 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001595 if !dh.reconciling {
1596 // create announce the UniPort to the core as VOLTHA Port object
Himani Chawla6d2ae152020-09-02 13:11:20 +05301597 if err := pUniPort.createVolthaPort(dh); err == nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001598 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1599 } //error logging already within UniPort method
1600 } else {
1601 logger.Debugw("reconciling - onuUniPort already added", log.Fields{"for PortNo": uniNo, "device-id": dh.deviceID})
1602 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001603 }
1604 }
1605}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001606
mpagenko3af1f032020-06-10 08:53:41 +00001607// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05301608func (dh *deviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001609 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
Himani Chawla4d908332020-08-31 12:30:20 +05301610 // but towards core only the first port active state is signaled
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001611 // with following remark:
1612 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1613 // # load on the core
1614
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001615 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001616
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001617 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001618 // only if this port is validated for operState transfer
Himani Chawla6d2ae152020-09-02 13:11:20 +05301619 if (1<<uniPort.uniID)&activeUniPortStateUpdateMask == (1 << uniPort.uniID) {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001620 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301621 uniPort.setOperState(vc.OperStatus_ACTIVE)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001622 if !dh.reconciling {
1623 //maybe also use getter functions on uniPort - perhaps later ...
1624 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1625 } else {
Andrea Campanellaab7b6a52020-10-06 16:17:13 +02001626 //TODO there is no retry mechanism, return error
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001627 logger.Debugw("reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
1628 }
mpagenko3af1f032020-06-10 08:53:41 +00001629 }
1630 }
1631}
1632
1633// Disable UniPortState and update core port state accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05301634func (dh *deviceHandler) disableUniPortStateUpdate() {
mpagenko3af1f032020-06-10 08:53:41 +00001635 // compare enableUniPortStateUpdate() above
1636 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1637 for uniNo, uniPort := range dh.uniEntityMap {
1638 // only if this port is validated for operState transfer
Himani Chawla6d2ae152020-09-02 13:11:20 +05301639 if (1<<uniPort.uniID)&activeUniPortStateUpdateMask == (1 << uniPort.uniID) {
mpagenko3af1f032020-06-10 08:53:41 +00001640 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301641 uniPort.setOperState(vc.OperStatus_UNKNOWN)
mpagenko3af1f032020-06-10 08:53:41 +00001642 //maybe also use getter functions on uniPort - perhaps later ...
1643 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001644 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001645 }
1646}
1647
1648// ONU_Active/Inactive announcement on system KAFKA bus
1649// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
Himani Chawla6d2ae152020-09-02 13:11:20 +05301650func (dh *deviceHandler) sendOnuOperStateEvent(aOperState vc.OperStatus_Types, aDeviceID string, raisedTs int64) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001651 var de voltha.DeviceEvent
1652 eventContext := make(map[string]string)
1653 //Populating event context
1654 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
Himani Chawla4d908332020-08-31 12:30:20 +05301655 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentID, dh.parentID)
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001656 if err != nil || parentDevice == nil {
1657 logger.Errorw("Failed to fetch parent device for OnuEvent",
Himani Chawla4d908332020-08-31 12:30:20 +05301658 log.Fields{"parentID": dh.parentID, "err": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001659 }
1660 oltSerialNumber := parentDevice.SerialNumber
1661
1662 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1663 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1664 eventContext["serial-number"] = dh.device.SerialNumber
1665 eventContext["olt_serial_number"] = oltSerialNumber
Himani Chawla4d908332020-08-31 12:30:20 +05301666 eventContext["device_id"] = aDeviceID
1667 eventContext["registration_id"] = aDeviceID //py: string(device_id)??
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001668 logger.Debugw("prepare ONU_ACTIVATED event",
Himani Chawla4d908332020-08-31 12:30:20 +05301669 log.Fields{"DeviceId": aDeviceID, "EventContext": eventContext})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001670
1671 /* Populating device event body */
1672 de.Context = eventContext
Himani Chawla4d908332020-08-31 12:30:20 +05301673 de.ResourceId = aDeviceID
1674 if aOperState == voltha.OperStatus_ACTIVE {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001675 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1676 de.Description = fmt.Sprintf("%s Event - %s - %s",
1677 cEventObjectType, cOnuActivatedEvent, "Raised")
1678 } else {
1679 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1680 de.Description = fmt.Sprintf("%s Event - %s - %s",
1681 cEventObjectType, cOnuActivatedEvent, "Cleared")
1682 }
1683 /* Send event to KAFKA */
1684 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1685 logger.Warnw("could not send ONU_ACTIVATED event",
Himani Chawla4d908332020-08-31 12:30:20 +05301686 log.Fields{"device-id": aDeviceID, "error": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001687 }
1688 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
Himani Chawla4d908332020-08-31 12:30:20 +05301689 log.Fields{"device-id": aDeviceID, "with-EventName": de.DeviceEventName})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001690}
1691
Himani Chawla4d908332020-08-31 12:30:20 +05301692// createUniLockFsm initializes and runs the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Himani Chawla6d2ae152020-09-02 13:11:20 +05301693func (dh *deviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001694 chLSFsm := make(chan Message, 2048)
1695 var sFsmName string
Himani Chawla4d908332020-08-31 12:30:20 +05301696 if aAdminState {
divyadesai4d299552020-08-18 07:13:49 +00001697 logger.Infow("createLockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001698 sFsmName = "LockStateFSM"
1699 } else {
divyadesai4d299552020-08-18 07:13:49 +00001700 logger.Infow("createUnlockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001701 sFsmName = "UnLockStateFSM"
1702 }
mpagenko3af1f032020-06-10 08:53:41 +00001703
Himani Chawla6d2ae152020-09-02 13:11:20 +05301704 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenko3af1f032020-06-10 08:53:41 +00001705 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001706 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001707 return
1708 }
Himani Chawla6d2ae152020-09-02 13:11:20 +05301709 pLSFsm := newLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001710 sFsmName, dh, chLSFsm)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001711 if pLSFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301712 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001713 dh.pLockStateFsm = pLSFsm
1714 } else {
1715 dh.pUnlockStateFsm = pLSFsm
1716 }
1717 dh.runUniLockFsm(aAdminState)
1718 } else {
divyadesai4d299552020-08-18 07:13:49 +00001719 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001720 }
1721}
1722
1723// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Himani Chawla6d2ae152020-09-02 13:11:20 +05301724func (dh *deviceHandler) runUniLockFsm(aAdminState bool) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001725 /* Uni Port lock/unlock procedure -
1726 ***** should run via 'adminDone' state and generate the argument requested event *****
1727 */
1728 var pLSStatemachine *fsm.FSM
Himani Chawla4d908332020-08-31 12:30:20 +05301729 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001730 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1731 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1732 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001733 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301734 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001735 }
1736 } else {
1737 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1738 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1739 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001740 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301741 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001742 }
1743 }
1744 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001745 if pLSStatemachine.Is(uniStDisabled) {
1746 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001747 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1748 // maybe try a FSM reset and then again ... - TODO!!!
1749 } else {
1750 /***** LockStateFSM started */
1751 logger.Debugw("LockStateFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001752 "state": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001753 }
1754 } else {
1755 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001756 "have": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001757 // maybe try a FSM reset and then again ... - TODO!!!
1758 }
1759 } else {
divyadesai4d299552020-08-18 07:13:49 +00001760 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001761 // maybe try a FSM reset and then again ... - TODO!!!
1762 }
1763}
1764
Himani Chawla6d2ae152020-09-02 13:11:20 +05301765//setBackend provides a DB backend for the specified path on the existing KV client
1766func (dh *deviceHandler) setBackend(aBasePathKvStore string) *db.Backend {
mpagenkoaf801632020-07-03 10:00:42 +00001767 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1768 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
divyadesai4d299552020-08-18 07:13:49 +00001769 "BasePathKvStore": aBasePathKvStore, "device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +00001770 kvbackend := &db.Backend{
1771 Client: dh.pOpenOnuAc.kvClient,
1772 StoreType: dh.pOpenOnuAc.KVStoreType,
1773 /* address config update acc. to [VOL-2736] */
1774 Address: addr,
1775 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1776 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001777
mpagenkoaf801632020-07-03 10:00:42 +00001778 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001779}
Himani Chawla6d2ae152020-09-02 13:11:20 +05301780func (dh *deviceHandler) getFlowOfbFields(apFlowItem *ofp.OfpFlowStats, loMatchVlan *uint16,
Himani Chawla26e555c2020-08-31 12:30:20 +05301781 loAddPcp *uint8, loIPProto *uint32) {
mpagenkodff5dda2020-08-28 11:52:01 +00001782
mpagenkodff5dda2020-08-28 11:52:01 +00001783 for _, field := range flow.GetOfbFields(apFlowItem) {
1784 switch field.Type {
1785 case of.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
1786 {
1787 logger.Debugw("FlowAdd type EthType", log.Fields{"device-id": dh.deviceID,
1788 "EthType": strconv.FormatInt(int64(field.GetEthType()), 16)})
1789 }
1790 case of.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
1791 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301792 *loIPProto = field.GetIpProto()
mpagenkodff5dda2020-08-28 11:52:01 +00001793 logger.Debugw("FlowAdd type IpProto", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301794 "IpProto": strconv.FormatInt(int64(*loIPProto), 16)})
1795 if *loIPProto == 2 {
mpagenkodff5dda2020-08-28 11:52:01 +00001796 // some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
1797 // avoids installing invalid EVTOCD rule
1798 logger.Debugw("FlowAdd type IpProto 2: TT workaround: ignore flow",
1799 log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301800 "IpProto": strconv.FormatInt(int64(*loIPProto), 16)})
1801 return
mpagenkodff5dda2020-08-28 11:52:01 +00001802 }
1803 }
1804 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
1805 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301806 *loMatchVlan = uint16(field.GetVlanVid())
mpagenkodff5dda2020-08-28 11:52:01 +00001807 loMatchVlanMask := uint16(field.GetVlanVidMask())
Himani Chawla26e555c2020-08-31 12:30:20 +05301808 if !(*loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) &&
mpagenkodff5dda2020-08-28 11:52:01 +00001809 loMatchVlanMask == uint16(of.OfpVlanId_OFPVID_PRESENT)) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301810 *loMatchVlan = *loMatchVlan & 0xFFF // not transparent: copy only ID bits
mpagenkodff5dda2020-08-28 11:52:01 +00001811 }
1812 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301813 "VID": strconv.FormatInt(int64(*loMatchVlan), 16)})
mpagenkodff5dda2020-08-28 11:52:01 +00001814 }
1815 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
1816 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301817 *loAddPcp = uint8(field.GetVlanPcp())
mpagenkodff5dda2020-08-28 11:52:01 +00001818 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1819 "PCP": loAddPcp})
1820 }
1821 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
1822 {
1823 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1824 "UDP-DST": strconv.FormatInt(int64(field.GetUdpDst()), 16)})
1825 }
1826 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
1827 {
1828 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1829 "UDP-SRC": strconv.FormatInt(int64(field.GetUdpSrc()), 16)})
1830 }
1831 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
1832 {
1833 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1834 "IPv4-DST": field.GetIpv4Dst()})
1835 }
1836 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC:
1837 {
1838 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1839 "IPv4-SRC": field.GetIpv4Src()})
1840 }
1841 case of.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
1842 {
1843 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1844 "Metadata": field.GetTableMetadata()})
1845 }
1846 /*
1847 default:
1848 {
1849 //all other entires ignored
1850 }
1851 */
1852 }
1853 } //for all OfbFields
Himani Chawla26e555c2020-08-31 12:30:20 +05301854}
mpagenkodff5dda2020-08-28 11:52:01 +00001855
Himani Chawla6d2ae152020-09-02 13:11:20 +05301856func (dh *deviceHandler) getFlowActions(apFlowItem *ofp.OfpFlowStats, loSetPcp *uint8, loSetVlan *uint16) {
mpagenkodff5dda2020-08-28 11:52:01 +00001857 for _, action := range flow.GetActions(apFlowItem) {
1858 switch action.Type {
1859 /* not used:
1860 case of.OfpActionType_OFPAT_OUTPUT:
1861 {
1862 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1863 "Output": action.GetOutput()})
1864 }
1865 */
1866 case of.OfpActionType_OFPAT_PUSH_VLAN:
1867 {
1868 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1869 "PushEthType": strconv.FormatInt(int64(action.GetPush().Ethertype), 16)})
1870 }
1871 case of.OfpActionType_OFPAT_SET_FIELD:
1872 {
1873 pActionSetField := action.GetSetField()
1874 if pActionSetField.Field.OxmClass != of.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1875 logger.Warnw("FlowAdd action SetField invalid OxmClass (ignored)", log.Fields{"device-id": dh.deviceID,
1876 "OxcmClass": pActionSetField.Field.OxmClass})
1877 }
1878 if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Himani Chawla26e555c2020-08-31 12:30:20 +05301879 *loSetVlan = uint16(pActionSetField.Field.GetOfbField().GetVlanVid())
mpagenkodff5dda2020-08-28 11:52:01 +00001880 logger.Debugw("FlowAdd Set VLAN from SetField action", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301881 "SetVlan": strconv.FormatInt(int64(*loSetVlan), 16)})
mpagenkodff5dda2020-08-28 11:52:01 +00001882 } else if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
Himani Chawla26e555c2020-08-31 12:30:20 +05301883 *loSetPcp = uint8(pActionSetField.Field.GetOfbField().GetVlanPcp())
mpagenkodff5dda2020-08-28 11:52:01 +00001884 logger.Debugw("FlowAdd Set PCP from SetField action", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301885 "SetPcp": *loSetPcp})
mpagenkodff5dda2020-08-28 11:52:01 +00001886 } else {
1887 logger.Warnw("FlowAdd action SetField invalid FieldType", log.Fields{"device-id": dh.deviceID,
1888 "Type": pActionSetField.Field.GetOfbField().Type})
1889 }
1890 }
1891 /*
1892 default:
1893 {
1894 //all other entires ignored
1895 }
1896 */
1897 }
1898 } //for all Actions
Himani Chawla26e555c2020-08-31 12:30:20 +05301899}
1900
1901//addFlowItemToUniPort parses the actual flow item to add it to the UniPort
Himani Chawla6d2ae152020-09-02 13:11:20 +05301902func (dh *deviceHandler) addFlowItemToUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *onuUniPort) error {
Himani Chawla26e555c2020-08-31 12:30:20 +05301903 var loSetVlan uint16 = uint16(of.OfpVlanId_OFPVID_NONE) //noValidEntry
1904 var loMatchVlan uint16 = uint16(of.OfpVlanId_OFPVID_PRESENT) //reserved VLANID entry
1905 var loAddPcp, loSetPcp uint8
1906 var loIPProto uint32
1907 /* the TechProfileId is part of the flow Metadata - compare also comment within
1908 * OLT-Adapter:openolt_flowmgr.go
1909 * Metadata 8 bytes:
1910 * Most Significant 2 Bytes = Inner VLAN
1911 * Next 2 Bytes = Tech Profile ID(TPID)
1912 * Least Significant 4 Bytes = Port ID
1913 * Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1914 * subscriber related flows.
1915 */
1916
1917 metadata := flow.GetMetadataFromWriteMetadataAction(apFlowItem)
1918 if metadata == 0 {
1919 logger.Debugw("FlowAdd invalid metadata - abort",
1920 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001921 return fmt.Errorf("flowAdd invalid metadata: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +05301922 }
1923 loTpID := flow.GetTechProfileIDFromWriteMetaData(metadata)
1924 logger.Debugw("FlowAdd TechProfileId", log.Fields{"device-id": dh.deviceID, "TP-Id": loTpID})
1925
1926 dh.getFlowOfbFields(apFlowItem, &loMatchVlan, &loAddPcp, &loIPProto)
1927 if loIPProto == 2 {
1928 // some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
1929 // avoids installing invalid EVTOCD rule
1930 logger.Debugw("FlowAdd type IpProto 2: TT workaround: ignore flow",
1931 log.Fields{"device-id": dh.deviceID,
1932 "IpProto": strconv.FormatInt(int64(loIPProto), 16)})
1933 return nil
1934 }
1935 dh.getFlowActions(apFlowItem, &loSetPcp, &loSetVlan)
mpagenkodff5dda2020-08-28 11:52:01 +00001936
1937 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1938 logger.Errorw("FlowAdd aborted - SetVlanId undefined, but MatchVid set", log.Fields{
1939 "device-id": dh.deviceID, "UniPort": apUniPort.portNo,
1940 "set_vid": strconv.FormatInt(int64(loSetVlan), 16),
1941 "match_vid": strconv.FormatInt(int64(loMatchVlan), 16)})
1942 //TODO!!: Use DeviceId within the error response to rwCore
1943 // likewise also in other error response cases to calling components as requested in [VOL-3458]
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001944 return fmt.Errorf("flowAdd Set/Match VlanId inconsistent: %s", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001945 }
1946 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) {
1947 logger.Debugw("FlowAdd vlan-any/copy", log.Fields{"device-id": dh.deviceID})
1948 loSetVlan = loMatchVlan //both 'transparent' (copy any)
1949 } else {
1950 //looks like OMCI value 4097 (copyFromOuter - for Uni double tagged) is not supported here
1951 if loSetVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1952 // not set to transparent
Himani Chawla26e555c2020-08-31 12:30:20 +05301953 loSetVlan &= 0x0FFF //mask VID bits as prerequisite for vlanConfigFsm
mpagenkodff5dda2020-08-28 11:52:01 +00001954 }
1955 logger.Debugw("FlowAdd vlan-set", log.Fields{"device-id": dh.deviceID})
1956 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301957 if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001958 return dh.UniVlanConfigFsmMap[apUniPort.uniID].SetUniFlowParams(loTpID, loMatchVlan, loSetVlan, loSetPcp)
mpagenkodff5dda2020-08-28 11:52:01 +00001959 }
1960 return dh.createVlanFilterFsm(apUniPort,
1961 loTpID, loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterDone)
1962}
1963
Himani Chawla26e555c2020-08-31 12:30:20 +05301964// createVlanFilterFsm initializes and runs the VlanFilter FSM to transfer OMCI related VLAN config
Himani Chawla6d2ae152020-09-02 13:11:20 +05301965func (dh *deviceHandler) createVlanFilterFsm(apUniPort *onuUniPort,
mpagenkodff5dda2020-08-28 11:52:01 +00001966 aTpID uint16, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8, aDevEvent OnuDeviceEvent) error {
1967 chVlanFilterFsm := make(chan Message, 2048)
1968
Himani Chawla6d2ae152020-09-02 13:11:20 +05301969 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenkodff5dda2020-08-28 11:52:01 +00001970 if pDevEntry == nil {
1971 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301972 return fmt.Errorf("no valid OnuDevice for device-id %x - aborting", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001973 }
1974
1975 pVlanFilterFsm := NewUniVlanConfigFsm(dh, pDevEntry.PDevOmciCC, apUniPort, dh.pOnuTP,
1976 pDevEntry.pOnuDB, aTpID, aDevEvent, "UniVlanConfigFsm", dh.deviceID, chVlanFilterFsm,
1977 dh.pOpenOnuAc.AcceptIncrementalEvto, aMatchVlan, aSetVlan, aSetPcp)
1978 if pVlanFilterFsm != nil {
Himani Chawla26e555c2020-08-31 12:30:20 +05301979 dh.UniVlanConfigFsmMap[apUniPort.uniID] = pVlanFilterFsm
mpagenkodff5dda2020-08-28 11:52:01 +00001980 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1981 if pVlanFilterStatemachine != nil {
1982 if pVlanFilterStatemachine.Is(vlanStDisabled) {
1983 if err := pVlanFilterStatemachine.Event(vlanEvStart); err != nil {
1984 logger.Warnw("UniVlanConfigFsm: can't start", log.Fields{"err": err})
Himani Chawla26e555c2020-08-31 12:30:20 +05301985 return fmt.Errorf("can't start UniVlanConfigFsm for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001986 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301987 /***** UniVlanConfigFsm started */
1988 logger.Debugw("UniVlanConfigFsm started", log.Fields{
1989 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
1990 "UniPort": apUniPort.portNo})
mpagenkodff5dda2020-08-28 11:52:01 +00001991 } else {
1992 logger.Warnw("wrong state of UniVlanConfigFsm - want: disabled", log.Fields{
1993 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301994 return fmt.Errorf("uniVlanConfigFsm not in expected disabled state for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001995 }
1996 } else {
1997 logger.Errorw("UniVlanConfigFsm StateMachine invalid - cannot be executed!!", log.Fields{
1998 "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301999 return fmt.Errorf("uniVlanConfigFsm invalid for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002000 }
2001 } else {
2002 logger.Errorw("UniVlanConfigFsm could not be created - abort!!", log.Fields{
2003 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
Himani Chawla26e555c2020-08-31 12:30:20 +05302004 return fmt.Errorf("uniVlanConfigFsm could not be created for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002005 }
2006 return nil
2007}
2008
2009//verifyUniVlanConfigRequest checks on existence of flow configuration and starts it accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05302010func (dh *deviceHandler) verifyUniVlanConfigRequest(apUniPort *onuUniPort) {
mpagenkodff5dda2020-08-28 11:52:01 +00002011 //TODO!! verify and start pending flow configuration
2012 //some pending config request my exist in case the UniVlanConfig FSM was already started - with internal data -
2013 //but execution was set to 'on hold' as first the TechProfile config had to be applied
Himani Chawla26e555c2020-08-31 12:30:20 +05302014 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
mpagenkodff5dda2020-08-28 11:52:01 +00002015 //VlanFilterFsm exists and was already started (assumed to wait for TechProfile execution here)
2016 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
2017 if pVlanFilterStatemachine != nil {
2018 if pVlanFilterStatemachine.Is(vlanStWaitingTechProf) {
2019 if err := pVlanFilterStatemachine.Event(vlanEvContinueConfig); err != nil {
2020 logger.Warnw("UniVlanConfigFsm: can't continue processing", log.Fields{"err": err})
2021 } else {
2022 /***** UniVlanConfigFsm continued */
2023 logger.Debugw("UniVlanConfigFsm continued", log.Fields{
2024 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
2025 "UniPort": apUniPort.portNo})
2026 }
2027 } else {
2028 logger.Debugw("no state of UniVlanConfigFsm to be continued", log.Fields{
2029 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
2030 }
2031 } else {
2032 logger.Debugw("UniVlanConfigFsm StateMachine does not exist, no flow processing", log.Fields{
2033 "device-id": dh.deviceID})
2034 }
2035
2036 } // else: nothing to do
2037}
2038
2039//RemoveVlanFilterFsm deletes the stored pointer to the VlanConfigFsm
2040// intention is to provide this method to be called from VlanConfigFsm itself, when resources (and methods!) are cleaned up
Himani Chawla6d2ae152020-09-02 13:11:20 +05302041func (dh *deviceHandler) RemoveVlanFilterFsm(apUniPort *onuUniPort) {
mpagenkodff5dda2020-08-28 11:52:01 +00002042 logger.Debugw("remove UniVlanConfigFsm StateMachine", log.Fields{
2043 "device-id": dh.deviceID, "uniPort": apUniPort.portNo})
2044 //save to do, even if entry dows not exist
Himani Chawla26e555c2020-08-31 12:30:20 +05302045 delete(dh.UniVlanConfigFsmMap, apUniPort.uniID)
mpagenkodff5dda2020-08-28 11:52:01 +00002046}
Holger Hildebrandt47555e72020-09-21 11:07:24 +00002047
2048//storePersUniFlowConfig updates local storage of OnuUniFlowConfig and writes it into kv-store afterwards to have it
2049//available for potential reconcilement
2050
2051func (dh *deviceHandler) storePersUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]uniVlanFlowParams) error {
2052
2053 if dh.reconciling {
2054 logger.Debugw("reconciling - don't store persistent UniFlowConfig", log.Fields{"device-id": dh.deviceID})
2055 return nil
2056 }
2057 logger.Debugw("Store persistent UniFlowConfig", log.Fields{"device-id": dh.deviceID})
2058
2059 pDevEntry := dh.getOnuDeviceEntry(true)
2060 if pDevEntry == nil {
2061 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
2062 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
2063 }
2064 pDevEntry.updateOnuUniFlowConfig(aUniID, aUniVlanFlowParams)
2065
2066 pDevEntry.lockOnuKVStoreMutex()
2067 defer pDevEntry.unlockOnuKVStoreMutex()
2068
2069 // deadline context to ensure completion of background routines waited for
2070 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +05302071 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandt47555e72020-09-21 11:07:24 +00002072 dctx, cancel := context.WithDeadline(context.Background(), deadline)
2073
2074 pDevEntry.resetKvProcessingErrorIndication()
2075 var wg sync.WaitGroup
2076 wg.Add(1) // for the 1 go routine to finish
2077
2078 go pDevEntry.updateOnuKvStore(dctx, &wg)
2079 dh.waitForCompletion(cancel, &wg) //wait for background process to finish
2080
2081 return pDevEntry.getKvProcessingErrorIndication()
2082}
2083
2084func (dh *deviceHandler) waitForCompletion(cancel context.CancelFunc, wg *sync.WaitGroup) {
2085 defer cancel() //ensure termination of context (may be pro forma)
2086 wg.Wait()
2087 logger.Debug("WaitGroup processing completed")
2088
2089}
2090
2091func (dh *deviceHandler) combineErrorStrings(errS ...error) error {
2092 var errStr string = ""
2093 for _, err := range errS {
2094 if err != nil {
2095 errStr = errStr + err.Error() + " "
2096 }
2097 }
2098 if errStr != "" {
2099 return fmt.Errorf("%s: %s", errStr, dh.deviceID)
2100 }
2101 return nil
2102}