blob: 379daa019e311668e6e6bd7402735e8067ca1adf [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})
240 return errors.New("no valid OnuDevice")
241}
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()})
264 return errors.New("invalidOperState")
265 }
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 {
271 if dh.pOnuTP == nil {
272 //should normally not happen ...
273 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
274 log.Fields{"device-id": dh.deviceID})
275 return errors.New("techProfile DLMsg request while onuTechProf instance not setup")
276 }
277 if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
278 // I've seen cases for this request, where the device was already stopped
279 logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
280 return errors.New("device-unreachable")
281 }
282
283 msgBody := msg.GetBody()
284 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
285 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
286 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
287 "device-id": dh.deviceID, "error": err})
288 return err
289 }
290
291 // we have to lock access to TechProfile processing based on different messageType calls or
292 // even to fast subsequent calls of the same messageType
293 dh.pOnuTP.lockTpProcMutex()
294 // lock hangs as long as below decoupled or other related TechProfile processing is active
295 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify {
296 // if there has been some change for some uni TechProfilePath
297 //in order to allow concurrent calls to other dh instances we do not wait for execution here
298 //but doing so we can not indicate problems to the caller (who does what with that then?)
299 //by now we just assume straightforward successful execution
300 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
301 // possible problems to the caller later autonomously
302
303 // deadline context to ensure completion of background routines waited for
304 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
305 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
306 dctx, cancel := context.WithDeadline(context.Background(), deadline)
307
308 dh.pOnuTP.resetProcessingErrorIndication()
309 var wg sync.WaitGroup
310 wg.Add(2) // for the 2 go routines to finish
311 // attention: deadline completion check and wg.Done is to be done in both routines
312 go dh.pOnuTP.configureUniTp(dctx, uint8(techProfMsg.UniId), techProfMsg.Path, &wg)
313 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
314 //the wait.. function is responsible for tpProcMutex.Unlock()
315 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
316 return err
317 }
318 // no change, nothing really to do
319 dh.pOnuTP.unlockTpProcMutex()
320 //return success
321 return nil
322}
323
Himani Chawla6d2ae152020-09-02 13:11:20 +0530324func (dh *deviceHandler) processInterAdapterDeleteGemPortReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530325 msg *ic.InterAdapterMessage) error {
326
327 if dh.pOnuTP == nil {
328 //should normally not happen ...
329 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
330 log.Fields{"device-id": dh.deviceID})
331 return errors.New("techProfile DelGem request while onuTechProf instance not setup")
332 }
333
334 msgBody := msg.GetBody()
335 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
336 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
337 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
338 "device-id": dh.deviceID, "error": err})
339 return err
340 }
341
342 //compare TECH_PROFILE_DOWNLOAD_REQUEST
343 dh.pOnuTP.lockTpProcMutex()
344
345 // deadline context to ensure completion of background routines waited for
346 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
347 dctx, cancel := context.WithDeadline(context.Background(), deadline)
348
349 dh.pOnuTP.resetProcessingErrorIndication()
350 var wg sync.WaitGroup
351 wg.Add(1) // for the 1 go routine to finish
352 go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
353 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
354 //the wait.. function is responsible for tpProcMutex.Unlock()
355 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
356 return err
357}
358
Himani Chawla6d2ae152020-09-02 13:11:20 +0530359func (dh *deviceHandler) processInterAdapterDeleteTcontReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530360 msg *ic.InterAdapterMessage) error {
361 if dh.pOnuTP == nil {
362 //should normally not happen ...
363 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
364 log.Fields{"device-id": dh.deviceID})
365 return errors.New("techProfile DelTcont request while onuTechProf instance not setup")
366 }
367
368 msgBody := msg.GetBody()
369 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
370 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
371 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
372 "device-id": dh.deviceID, "error": err})
373 return err
374 }
375
376 //compare TECH_PROFILE_DOWNLOAD_REQUEST
377 dh.pOnuTP.lockTpProcMutex()
378 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify {
379 // deadline context to ensure completion of background routines waited for
380 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
381 dctx, cancel := context.WithDeadline(context.Background(), deadline)
382
383 dh.pOnuTP.resetProcessingErrorIndication()
384 var wg sync.WaitGroup
385 wg.Add(2) // for the 2 go routines to finish
386 go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
387 cResourceTcont, delTcontMsg.AllocId, &wg)
388 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
389 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
390 //the wait.. function is responsible for tpProcMutex.Unlock()
391 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
392 return err
393 }
394 dh.pOnuTP.unlockTpProcMutex()
395 //return success
396 return nil
397}
398
Himani Chawla6d2ae152020-09-02 13:11:20 +0530399//processInterAdapterMessage sends the proxied messages to the target device
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000400// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
401// is meant, and then send the unmarshalled omci message to this onu
Himani Chawla6d2ae152020-09-02 13:11:20 +0530402func (dh *deviceHandler) processInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000403 msgID := msg.Header.Id
404 msgType := msg.Header.Type
405 fromTopic := msg.Header.FromTopic
406 toTopic := msg.Header.ToTopic
407 toDeviceID := msg.Header.ToDeviceId
408 proxyDeviceID := msg.Header.ProxyDeviceId
409 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
410 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
411
412 switch msgType {
413 case ic.InterAdapterMessageType_OMCI_REQUEST:
414 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530415 return dh.processInterAdapterOMCIReqMessage(msg)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000416 }
417 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
418 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530419 return dh.processInterAdapterONUIndReqMessage(msg)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000420 }
mpagenkoaf801632020-07-03 10:00:42 +0000421 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
422 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530423 return dh.processInterAdapterTechProfileDownloadReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000424 }
425 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
426 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530427 return dh.processInterAdapterDeleteGemPortReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000428
mpagenkoaf801632020-07-03 10:00:42 +0000429 }
430 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
431 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530432 return dh.processInterAdapterDeleteTcontReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000433 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000434 default:
435 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000436 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000437 "device-id": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000438 return errors.New("unimplemented")
439 }
440 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000441}
442
mpagenkodff5dda2020-08-28 11:52:01 +0000443//FlowUpdateIncremental removes and/or adds the flow changes on a given device
Himani Chawla6d2ae152020-09-02 13:11:20 +0530444func (dh *deviceHandler) FlowUpdateIncremental(apOfFlowChanges *openflow_13.FlowChanges,
mpagenkodff5dda2020-08-28 11:52:01 +0000445 apOfGroupChanges *openflow_13.FlowGroupChanges, apFlowMetaData *voltha.FlowMetadata) error {
446
447 //Remove flows
448 if apOfFlowChanges.ToRemove != nil {
449 for _, flowItem := range apOfFlowChanges.ToRemove.Items {
450 logger.Debugw("incremental flow item remove", log.Fields{"deviceId": dh.deviceID,
451 "Item": flowItem})
452 }
453 }
454 if apOfFlowChanges.ToAdd != nil {
455 for _, flowItem := range apOfFlowChanges.ToAdd.Items {
456 if flowItem.GetCookie() == 0 {
457 logger.Debugw("incremental flow add - no cookie - ignore", log.Fields{
458 "deviceId": dh.deviceID})
459 continue
460 }
461 flowInPort := flow.GetInPort(flowItem)
462 if flowInPort == uint32(of.OfpPortNo_OFPP_INVALID) {
463 logger.Errorw("flow inPort invalid", log.Fields{"deviceID": dh.deviceID})
464 return errors.New("flow inPort invalid")
465 } else if flowInPort == dh.ponPortNumber {
466 //this is some downstream flow
467 logger.Debugw("incremental flow ignore downstream", log.Fields{
468 "deviceId": dh.deviceID, "inPort": flowInPort})
469 continue
470 } else {
471 // this is the relevant upstream flow
Himani Chawla6d2ae152020-09-02 13:11:20 +0530472 var loUniPort *onuUniPort
mpagenkodff5dda2020-08-28 11:52:01 +0000473 if uniPort, exist := dh.uniEntityMap[flowInPort]; exist {
474 loUniPort = uniPort
475 } else {
476 logger.Errorw("flow inPort not found in UniPorts",
477 log.Fields{"deviceID": dh.deviceID, "inPort": flowInPort})
478 return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
479 }
480 flowOutPort := flow.GetOutPort(flowItem)
481 logger.Debugw("incremental flow-add port indications", log.Fields{
482 "deviceId": dh.deviceID, "inPort": flowInPort, "outPort": flowOutPort,
483 "uniPortName": loUniPort.name})
484 err := dh.addFlowItemToUniPort(flowItem, loUniPort)
485 //abort processing in error case
486 if err != nil {
487 return err
488 }
489 }
490 }
491 }
492 return nil
493}
494
Himani Chawla6d2ae152020-09-02 13:11:20 +0530495//disableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000496// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
497// maybe it is obsolete by now
Himani Chawla6d2ae152020-09-02 13:11:20 +0530498func (dh *deviceHandler) disableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000499 logger.Debugw("disable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000500
mpagenko3af1f032020-06-10 08:53:41 +0000501 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
502 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
503 if dh.deviceReason != "omci-admin-lock" {
504 // disable UNI ports/ONU
505 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
506 // here the result of the processing is not checked (trusted in background) *****
507 if dh.pLockStateFsm == nil {
508 dh.createUniLockFsm(true, UniAdminStateDone)
509 } else { //LockStateFSM already init
Himani Chawla6d2ae152020-09-02 13:11:20 +0530510 dh.pLockStateFsm.setSuccessEvent(UniAdminStateDone)
mpagenko3af1f032020-06-10 08:53:41 +0000511 dh.runUniLockFsm(true)
512 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300513
mpagenko3af1f032020-06-10 08:53:41 +0000514 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000515 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000516 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000517 }
518 dh.deviceReason = "omci-admin-lock"
519 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
520 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
521 voltha.OperStatus_UNKNOWN); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000522 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000523 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000524 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300525 }
526}
527
Himani Chawla6d2ae152020-09-02 13:11:20 +0530528//reEnableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000529// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
530// maybe it is obsolete by now
Himani Chawla6d2ae152020-09-02 13:11:20 +0530531func (dh *deviceHandler) reEnableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000532 logger.Debugw("reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000533
534 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300535 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
536 voltha.OperStatus_ACTIVE); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000537 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000538 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300539 }
540
mpagenko3af1f032020-06-10 08:53:41 +0000541 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000542 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000543 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000544 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300545 }
mpagenko3af1f032020-06-10 08:53:41 +0000546 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000547
548 // enable ONU/UNI ports
549 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
550 // here the result of the processing is not checked (trusted in background) *****
551 if dh.pUnlockStateFsm == nil {
552 dh.createUniLockFsm(false, UniAdminStateDone)
553 } else { //UnlockStateFSM already init
Himani Chawla6d2ae152020-09-02 13:11:20 +0530554 dh.pUnlockStateFsm.setSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000555 dh.runUniLockFsm(false)
556 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300557}
558
Himani Chawla6d2ae152020-09-02 13:11:20 +0530559func (dh *deviceHandler) reconcileDeviceOnuInd() {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000560 logger.Debugw("reconciling - simulate onu indication", log.Fields{"device-id": dh.deviceID})
561
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000562 if err := dh.pOnuTP.restoreFromOnuTpPathKvStore(context.TODO()); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000563 logger.Errorw("reconciling - restoring OnuTp-data failed - abort", log.Fields{"err": err, "device-id": dh.deviceID})
564 dh.reconciling = false
565 return
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000566 }
Himani Chawla4d908332020-08-31 12:30:20 +0530567 var onuIndication oop.OnuIndication
568 onuIndication.IntfId = dh.pOnuTP.sOnuPersistentData.PersIntfID
569 onuIndication.OnuId = dh.pOnuTP.sOnuPersistentData.PersOnuID
570 onuIndication.OperState = dh.pOnuTP.sOnuPersistentData.PersOperState
571 onuIndication.AdminState = dh.pOnuTP.sOnuPersistentData.PersAdminState
572 _ = dh.createInterface(&onuIndication)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000573}
574
Himani Chawla6d2ae152020-09-02 13:11:20 +0530575func (dh *deviceHandler) reconcileDeviceTechProf() {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000576 logger.Debugw("reconciling - trigger tech profile config", log.Fields{"device-id": dh.deviceID})
577
578 dh.pOnuTP.lockTpProcMutex()
579 // lock hangs as long as below decoupled or other related TechProfile processing is active
580 for _, uniData := range dh.pOnuTP.sOnuPersistentData.PersUniTpPath {
581 //In order to allow concurrent calls to other dh instances we do not wait for execution here
582 //but doing so we can not indicate problems to the caller (who does what with that then?)
583 //by now we just assume straightforward successful execution
584 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
585 // possible problems to the caller later autonomously
586
587 // deadline context to ensure completion of background routines waited for
588 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
589 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
590 dctx, cancel := context.WithDeadline(context.Background(), deadline)
591
592 dh.pOnuTP.resetProcessingErrorIndication()
593 var wg sync.WaitGroup
594 wg.Add(1) // for the 1 go routines to finish
595 // attention: deadline completion check and wg.Done is to be done in both routines
Himani Chawla26e555c2020-08-31 12:30:20 +0530596 go dh.pOnuTP.configureUniTp(dctx, uint8(uniData.PersUniID), uniData.PersTpPath, &wg)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000597 //the wait.. function is responsible for tpProcMutex.Unlock()
Himani Chawla4d908332020-08-31 12:30:20 +0530598 _ = dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000599 return
600 }
601 dh.pOnuTP.unlockTpProcMutex()
602 //TODO: reset of reconciling-flag has always to be done in the last ReconcileDevice*() function
603 dh.reconciling = false
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000604}
605
Himani Chawla6d2ae152020-09-02 13:11:20 +0530606func (dh *deviceHandler) deleteDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000607 logger.Debugw("delete-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000608 if err := dh.pOnuTP.deleteOnuTpPathKvStore(context.TODO()); err != nil {
609 return err
610 }
611 // TODO: further actions - stop metrics and FSMs, remove device ...
612 return nil
613}
614
Himani Chawla6d2ae152020-09-02 13:11:20 +0530615func (dh *deviceHandler) rebootDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000616 logger.Debugw("reboot-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300617 if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
divyadesai4d299552020-08-18 07:13:49 +0000618 logger.Errorw("device-unreachable", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300619 return errors.New("device-unreachable")
620 }
Himani Chawla6d2ae152020-09-02 13:11:20 +0530621 if err := dh.pOnuOmciDevice.reboot(context.TODO()); err != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530622 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
623 logger.Errorw("error-rebooting-device", log.Fields{"device-id": dh.deviceID, "error": err})
624 return err
625 }
ozgecanetsiae11479f2020-07-06 09:44:47 +0300626 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
627 voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000628 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000629 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300630 return err
631 }
632 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting-onu"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000633 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000634 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300635 return err
636 }
637 dh.deviceReason = "rebooting-onu"
638 return nil
639}
640
Himani Chawla6d2ae152020-09-02 13:11:20 +0530641// deviceHandler methods that implement the adapters interface requests## end #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000642// #####################################################################################
643
644// ################ to be updated acc. needs of ONU Device ########################
Himani Chawla6d2ae152020-09-02 13:11:20 +0530645// deviceHandler StateMachine related state transition methods ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000646
Himani Chawla6d2ae152020-09-02 13:11:20 +0530647func (dh *deviceHandler) logStateChange(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000648 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})
649}
650
651// doStateInit provides the device update to the core
Himani Chawla6d2ae152020-09-02 13:11:20 +0530652func (dh *deviceHandler) doStateInit(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000653
654 logger.Debug("doStateInit-started")
655 var err error
656
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000657 // populate what we know. rest comes later after mib sync
658 dh.device.Root = false
659 dh.device.Vendor = "OpenONU"
660 dh.device.Model = "go"
661 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000662 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000663
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000664 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000665
666 if !dh.reconciling {
Himani Chawla4d908332020-08-31 12:30:20 +0530667 _ = dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000668 } else {
669 logger.Debugw("reconciling - don't notify core about DeviceUpdate",
670 log.Fields{"device-id": dh.deviceID})
671 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000672
Himani Chawla4d908332020-08-31 12:30:20 +0530673 dh.parentID = dh.device.ParentId
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000674 dh.ponPortNumber = dh.device.ParentPortNo
675
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000676 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
677 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
678 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
divyadesai4d299552020-08-18 07:13:49 +0000679 logger.Debugw("device-updated", log.Fields{"device-id": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000680 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Himani Chawla4d908332020-08-31 12:30:20 +0530681 "ParentId": dh.parentID, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000682
683 /*
684 self._pon = PonPort.create(self, self._pon_port_number)
685 self._pon.add_peer(self.parent_id, self._pon_port_number)
686 self.logger.debug('adding-pon-port-to-agent',
687 type=self._pon.get_port().type,
688 admin_state=self._pon.get_port().admin_state,
689 oper_status=self._pon.get_port().oper_status,
690 )
691 */
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000692 if !dh.reconciling {
693 logger.Debugw("adding-pon-port", log.Fields{"deviceID": dh.deviceID, "ponPortNo": dh.ponPortNumber})
694 var ponPortNo uint32 = 1
695 if dh.ponPortNumber != 0 {
696 ponPortNo = dh.ponPortNumber
697 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000698
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000699 pPonPort := &voltha.Port{
700 PortNo: ponPortNo,
701 Label: fmt.Sprintf("pon-%d", ponPortNo),
702 Type: voltha.Port_PON_ONU,
703 OperStatus: voltha.OperStatus_ACTIVE,
Himani Chawla4d908332020-08-31 12:30:20 +0530704 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentID, // Peer device is OLT
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000705 PortNo: ponPortNo}}, // Peer port is parent's port number
706 }
707 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
708 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
709 e.Cancel(err)
710 return
711 }
712 } else {
713 logger.Debugw("reconciling - pon-port already added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000714 }
715 logger.Debug("doStateInit-done")
716}
717
718// postInit setups the DeviceEntry for the conerned device
Himani Chawla6d2ae152020-09-02 13:11:20 +0530719func (dh *deviceHandler) postInit(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000720
721 logger.Debug("postInit-started")
722 var err error
723 /*
724 dh.Client = oop.NewOpenoltClient(dh.clientCon)
725 dh.pTransitionMap.Handle(ctx, GrpcConnected)
726 return nil
727 */
Himani Chawla6d2ae152020-09-02 13:11:20 +0530728 if err = dh.addOnuDeviceEntry(context.TODO()); err != nil {
729 logger.Fatalf("Device FSM: addOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000730 e.Cancel(err)
731 return
732 }
733
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000734 if dh.reconciling {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530735 go dh.reconcileDeviceOnuInd()
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000736 // reconcilement will be continued after mib download is done
737 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000738 /*
739 ############################################################################
740 # Setup Alarm handler
741 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
742 device.serial_number)
743 ############################################################################
744 # Setup PM configuration for this device
745 # Pass in ONU specific options
746 kwargs = {
747 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
748 'heartbeat': self.heartbeat,
749 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
750 }
751 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
752 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
753 self.logical_device_id, device.serial_number,
754 grouped=True, freq_override=False, **kwargs)
755 pm_config = self._pm_metrics.make_proto()
756 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
757 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
758 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
759
760 # Note, ONU ID and UNI intf set in add_uni_port method
761 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
762 ani_ports=[self._pon])
763
764 # Code to Run OMCI Test Action
765 kwargs_omci_test_action = {
766 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
767 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
768 }
769 serial_number = device.serial_number
770 self._test_request = OmciTestRequest(self.core_proxy,
771 self.omci_agent, self.device_id,
772 AniG, serial_number,
773 self.logical_device_id,
774 exclusive=False,
775 **kwargs_omci_test_action)
776
777 self.enabled = True
778 else:
779 self.logger.info('onu-already-activated')
780 */
781 logger.Debug("postInit-done")
782}
783
784// doStateConnected get the device info and update to voltha core
785// for comparison of the original method (not that easy to uncomment): compare here:
786// voltha-openolt-adapter/adaptercore/device_handler.go
787// -> this one obviously initiates all communication interfaces of the device ...?
Himani Chawla6d2ae152020-09-02 13:11:20 +0530788func (dh *deviceHandler) doStateConnected(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000789
790 logger.Debug("doStateConnected-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530791 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000792 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000793 logger.Debug("doStateConnected-done")
794}
795
796// doStateUp handle the onu up indication and update to voltha core
Himani Chawla6d2ae152020-09-02 13:11:20 +0530797func (dh *deviceHandler) doStateUp(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000798
799 logger.Debug("doStateUp-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530800 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000801 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000802 logger.Debug("doStateUp-done")
803
804 /*
805 // Synchronous call to update device state - this method is run in its own go routine
806 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
807 voltha.OperStatus_ACTIVE); err != nil {
808 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
809 return err
810 }
811 return nil
812 */
813}
814
815// doStateDown handle the onu down indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530816func (dh *deviceHandler) doStateDown(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000817
818 logger.Debug("doStateDown-started")
819 var err error
820
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000821 device := dh.device
822 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000823 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000824 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000825 e.Cancel(err)
826 return
827 }
828
829 cloned := proto.Clone(device).(*voltha.Device)
830 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
831 /*
832 // Update the all ports state on that device to disable
833 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
834 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
835 return er
836 }
837
838 //Update the device oper state and connection status
839 cloned.OperStatus = voltha.OperStatus_UNKNOWN
840 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
841 dh.device = cloned
842
843 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
844 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
845 return er
846 }
847
848 //get the child device for the parent device
849 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
850 if err != nil {
851 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
852 return err
853 }
854 for _, onuDevice := range onuDevices.Items {
855
856 // Update onu state as down in onu adapter
857 onuInd := oop.OnuIndication{}
858 onuInd.OperState = "down"
859 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
860 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
861 if er != nil {
862 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
863 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
864 //Do not return here and continue to process other ONUs
865 }
866 }
867 // * Discovered ONUs entries need to be cleared , since after OLT
868 // is up, it starts sending discovery indications again* /
869 dh.discOnus = sync.Map{}
870 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
871 return nil
872 */
Himani Chawla4d908332020-08-31 12:30:20 +0530873 err = errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000874 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000875 logger.Debug("doStateDown-done")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000876}
877
Himani Chawla6d2ae152020-09-02 13:11:20 +0530878// deviceHandler StateMachine related state transition methods ##### end #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000879// #################################################################################
880
881// ###################################################
Himani Chawla6d2ae152020-09-02 13:11:20 +0530882// deviceHandler utility methods ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000883
Himani Chawla6d2ae152020-09-02 13:11:20 +0530884//getOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
885func (dh *deviceHandler) getOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
mpagenko3af1f032020-06-10 08:53:41 +0000886 dh.lockDevice.RLock()
887 pOnuDeviceEntry := dh.pOnuOmciDevice
888 if aWait && pOnuDeviceEntry == nil {
889 //keep the read sema short to allow for subsequent write
890 dh.lockDevice.RUnlock()
divyadesai4d299552020-08-18 07:13:49 +0000891 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000892 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
893 // so it might be needed to wait here for that event with some timeout
894 select {
895 case <-time.After(60 * time.Second): //timer may be discussed ...
divyadesai4d299552020-08-18 07:13:49 +0000896 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000897 return nil
898 case <-dh.deviceEntrySet:
divyadesai4d299552020-08-18 07:13:49 +0000899 logger.Debugw("devicEntry ready now - continue", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000900 // if written now, we can return the written value without sema
901 return dh.pOnuOmciDevice
902 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000903 }
mpagenko3af1f032020-06-10 08:53:41 +0000904 dh.lockDevice.RUnlock()
905 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000906}
907
Himani Chawla6d2ae152020-09-02 13:11:20 +0530908//setOnuDeviceEntry sets the ONU device entry within the handler
909func (dh *deviceHandler) setOnuDeviceEntry(
910 apDeviceEntry *OnuDeviceEntry, apOnuTp *onuUniTechProf) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000911 dh.lockDevice.Lock()
912 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000913 dh.pOnuOmciDevice = apDeviceEntry
914 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000915}
916
Himani Chawla6d2ae152020-09-02 13:11:20 +0530917//addOnuDeviceEntry creates a new ONU device or returns the existing
918func (dh *deviceHandler) addOnuDeviceEntry(ctx context.Context) error {
divyadesai4d299552020-08-18 07:13:49 +0000919 logger.Debugw("adding-deviceEntry", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000920
Himani Chawla6d2ae152020-09-02 13:11:20 +0530921 deviceEntry := dh.getOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000922 if deviceEntry == nil {
923 /* costum_me_map in python code seems always to be None,
924 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
925 /* also no 'clock' argument - usage open ...*/
926 /* and no alarm_db yet (oo.alarm_db) */
Himani Chawla6d2ae152020-09-02 13:11:20 +0530927 deviceEntry = newOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
mpagenkoaf801632020-07-03 10:00:42 +0000928 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000929 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000930 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
Himani Chawla6d2ae152020-09-02 13:11:20 +0530931 onuTechProfProc := newOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000932 //error treatment possible //TODO!!!
Himani Chawla6d2ae152020-09-02 13:11:20 +0530933 dh.setOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000934 // fire deviceEntry ready event to spread to possibly waiting processing
935 dh.deviceEntrySet <- true
divyadesai4d299552020-08-18 07:13:49 +0000936 logger.Infow("onuDeviceEntry-added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000937 } else {
divyadesai4d299552020-08-18 07:13:49 +0000938 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000939 }
940 // might be updated with some error handling !!!
941 return nil
942}
943
944// doStateInit provides the device update to the core
Himani Chawla6d2ae152020-09-02 13:11:20 +0530945func (dh *deviceHandler) createInterface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000946 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
947 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
948
949 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000950
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000951 if !dh.reconciling {
952 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
953 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
954 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
955 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
956 }
957 } else {
958 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVATING",
959 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000960 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000961 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
962 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
963 // 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 +0000964 // 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 +0000965 // so let's just try to keep it simple ...
966 /*
967 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
968 if err != nil || device == nil {
969 //TODO: needs to handle error scenarios
970 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
971 return errors.New("Voltha Device not found")
972 }
973 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000974
Himani Chawla6d2ae152020-09-02 13:11:20 +0530975 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenko3af1f032020-06-10 08:53:41 +0000976 if pDevEntry != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530977 if err := pDevEntry.start(context.TODO()); err != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530978 return err
979 }
mpagenko3af1f032020-06-10 08:53:41 +0000980 } else {
divyadesai4d299552020-08-18 07:13:49 +0000981 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530982 return errors.New("no valid OnuDevice")
mpagenko3af1f032020-06-10 08:53:41 +0000983 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000984 if !dh.reconciling {
985 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
986 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
987 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"device-id": dh.deviceID, "error": err})
988 }
989 } else {
990 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to starting-openomci",
991 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000992 }
mpagenko3af1f032020-06-10 08:53:41 +0000993 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000994
995 /* this might be a good time for Omci Verify message? */
996 verifyExec := make(chan bool)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530997 omciVerify := newOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000998 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000999 true, true) //eclusive and allowFailure (anyway not yet checked)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301000 omciVerify.performOmciTest(context.TODO(), verifyExec)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001001
1002 /* give the handler some time here to wait for the OMCi verification result
1003 after Timeout start and try MibUpload FSM anyway
1004 (to prevent stopping on just not supported OMCI verification from ONU) */
1005 select {
1006 case <-time.After(2 * time.Second):
1007 logger.Warn("omci start-verification timed out (continue normal)")
1008 case testresult := <-verifyExec:
1009 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
1010 }
1011
1012 /* In py code it looks earlier (on activate ..)
1013 # Code to Run OMCI Test Action
1014 kwargs_omci_test_action = {
1015 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
1016 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
1017 }
1018 serial_number = device.serial_number
1019 self._test_request = OmciTestRequest(self.core_proxy,
1020 self.omci_agent, self.device_id,
1021 AniG, serial_number,
1022 self.logical_device_id,
1023 exclusive=False,
1024 **kwargs_omci_test_action)
1025 ...
1026 # Start test requests after a brief pause
1027 if not self._test_request_started:
1028 self._test_request_started = True
1029 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
1030 reactor.callLater(tststart, self._test_request.start_collector)
1031
1032 */
1033 /* which is then: in omci_test_request.py : */
1034 /*
1035 def start_collector(self, callback=None):
1036 """
1037 Start the collection loop for an adapter if the frequency > 0
1038
1039 :param callback: (callable) Function to call to collect PM data
1040 """
1041 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
1042 if callback is None:
1043 callback = self.perform_test_omci
1044
1045 if self.lc is None:
1046 self.lc = LoopingCall(callback)
1047
1048 if self.default_freq > 0:
1049 self.lc.start(interval=self.default_freq / 10)
1050
1051 def perform_test_omci(self):
1052 """
1053 Perform the initial test request
1054 """
1055 ani_g_entities = self._device.configuration.ani_g_entities
1056 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
1057 is not None else None
1058 self._entity_id = ani_g_entities_ids[0]
1059 self.logger.info('perform-test', entity_class=self._entity_class,
1060 entity_id=self._entity_id)
1061 try:
1062 frame = MEFrame(self._entity_class, self._entity_id, []).test()
1063 result = yield self._device.omci_cc.send(frame)
1064 if not result.fields['omci_message'].fields['success_code']:
1065 self.logger.info('Self-Test Submitted Successfully',
1066 code=result.fields[
1067 'omci_message'].fields['success_code'])
1068 else:
1069 raise TestFailure('Test Failure: {}'.format(
1070 result.fields['omci_message'].fields['success_code']))
1071 except TimeoutError as e:
1072 self.deferred.errback(failure.Failure(e))
1073
1074 except Exception as e:
1075 self.logger.exception('perform-test-Error', e=e,
1076 class_id=self._entity_class,
1077 entity_id=self._entity_id)
1078 self.deferred.errback(failure.Failure(e))
1079
1080 */
1081
1082 // PM related heartbeat??? !!!TODO....
1083 //self._heartbeat.enabled = True
1084
mpagenko1cc3cb42020-07-27 15:24:38 +00001085 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
1086 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
1087 * 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 +05301088 * otherwise some processing synchronization would be required - cmp. e.g TechProfile processing
mpagenko1cc3cb42020-07-27 15:24:38 +00001089 */
1090 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +00001091 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001092 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001093 if pMibUlFsm.Is(ulStDisabled) {
1094 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001095 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
Himani Chawla4d908332020-08-31 12:30:20 +05301096 return errors.New("can't go to state starting")
1097 }
1098 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1099 //Determine ONU status and start/re-start MIB Synchronization tasks
1100 //Determine if this ONU has ever synchronized
1101 if true { //TODO: insert valid check
1102 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
1103 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
1104 return errors.New("can't go to state resetting_mib")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001105 }
Himani Chawla4d908332020-08-31 12:30:20 +05301106 } else {
1107 if err := pMibUlFsm.Event(ulEvExamineMds); err != nil {
1108 logger.Errorw("MibSyncFsm: Can't go to state examine_mds", log.Fields{"err": err})
1109 return errors.New("can't go to examine_mds")
1110 }
1111 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1112 //Examine the MIB Data Sync
1113 // callbacks to be handled:
1114 // Event(ulEvSuccess)
1115 // Event(ulEvTimeout)
1116 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001117 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001118 } else {
1119 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
1120 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001121 }
1122 } else {
divyadesai4d299552020-08-18 07:13:49 +00001123 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001124 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001125 }
1126 return nil
1127}
1128
Himani Chawla6d2ae152020-09-02 13:11:20 +05301129func (dh *deviceHandler) updateInterface(onuind *oop.OnuIndication) error {
mpagenko3af1f032020-06-10 08:53:41 +00001130 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
1131 if dh.deviceReason != "stopping-openomci" {
divyadesai4d299552020-08-18 07:13:49 +00001132 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001133 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
Himani Chawla6d2ae152020-09-02 13:11:20 +05301134 pDevEntry := dh.getOnuDeviceEntry(false)
mpagenko3af1f032020-06-10 08:53:41 +00001135 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001136 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301137 return errors.New("no valid OnuDevice")
mpagenko3af1f032020-06-10 08:53:41 +00001138 }
1139
1140 switch dh.deviceReason {
1141 case "starting-openomci":
1142 { //MIBSync FSM may run
1143 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
1144 if pMibUlFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301145 _ = pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +00001146 }
1147 }
1148 case "discovery-mibsync-complete":
1149 { //MibDownload may run
1150 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1151 if pMibDlFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301152 _ = pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001153 }
1154 }
1155 default:
mpagenko3dbcdd22020-07-22 07:38:45 +00001156 {
1157 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +00001158 if dh.pUnlockStateFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301159 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001160 }
1161 if dh.pLockStateFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301162 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001163 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001164 //techProfile related PonAniConfigFsm FSM may be active
1165 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
1166 if dh.pOnuTP.pAniConfigFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301167 _ = dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +00001168 }
mpagenkodff5dda2020-08-28 11:52:01 +00001169 for _, uniPort := range dh.uniEntityMap {
1170 //reset the TechProfileConfig Done state for all (active) UNI's
Himani Chawla26e555c2020-08-31 12:30:20 +05301171 dh.pOnuTP.setConfigDone(uniPort.uniID, false)
1172 // reset the possibly existing VlanConfigFsm
1173 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[uniPort.uniID]; exist {
mpagenkodff5dda2020-08-28 11:52:01 +00001174 //VlanFilterFsm exists and was already started
1175 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1176 if pVlanFilterStatemachine != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301177 _ = pVlanFilterStatemachine.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001178 }
1179 }
1180 }
mpagenko3af1f032020-06-10 08:53:41 +00001181 }
1182 //TODO!!! care about PM/Alarm processing once started
1183 }
1184 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
Himani Chawla4d908332020-08-31 12:30:20 +05301185 // (mainly the still separate 'Event states')
mpagenko3af1f032020-06-10 08:53:41 +00001186 // so it is questionable, how this is resolved after some possible re-enable
1187 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1188
1189 //stop/remove(?) the device entry
Himani Chawla6d2ae152020-09-02 13:11:20 +05301190 _ = pDevEntry.stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
mpagenko3af1f032020-06-10 08:53:41 +00001191
1192 //TODO!!! remove existing traffic profiles
1193 /* from py code, if TP's exist, remove them - not yet implemented
1194 self._tp = dict()
1195 # Let TP download happen again
1196 for uni_id in self._tp_service_specific_task:
1197 self._tp_service_specific_task[uni_id].clear()
1198 for uni_id in self._tech_profile_download_done:
1199 self._tech_profile_download_done[uni_id].clear()
1200 */
1201
1202 dh.disableUniPortStateUpdate()
1203
1204 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001205 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001206 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
divyadesai4d299552020-08-18 07:13:49 +00001207 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001208 // abort: system behavior is just unstable ...
1209 return err
1210 }
1211 dh.deviceReason = "stopping-openomci"
1212
1213 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1214 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001215 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001216 logger.Errorw("error-updating-device-state unreachable-discovered",
divyadesai4d299552020-08-18 07:13:49 +00001217 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001218 // abort: system behavior is just unstable ...
1219 return err
1220 }
1221 } else {
divyadesai4d299552020-08-18 07:13:49 +00001222 logger.Debugw("updateInterface - device already stopped", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001223 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001224 return nil
1225}
1226
Himani Chawla6d2ae152020-09-02 13:11:20 +05301227func (dh *deviceHandler) processMibDatabaseSyncEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301228 logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
1229 if !dh.reconciling {
1230 //initiate DevStateUpdate
1231 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1232 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1233 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1234 "device-id": dh.deviceID, "error": err})
1235 } else {
1236 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
1237 }
1238 } else {
1239 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
1240 log.Fields{"device-id": dh.deviceID})
1241 }
1242 //set internal state anyway - as it was done
1243 dh.deviceReason = "discovery-mibsync-complete"
1244
1245 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301246 pDevEntry := dh.getOnuDeviceEntry(false)
1247 if unigInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301248 for _, mgmtEntityID := range unigInstKeys {
1249 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1250 "device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301251 dh.addUniPort(mgmtEntityID, i, uniPPTP)
Himani Chawla26e555c2020-08-31 12:30:20 +05301252 i++
1253 }
1254 } else {
1255 logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
1256 }
Himani Chawla6d2ae152020-09-02 13:11:20 +05301257 if veipInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301258 for _, mgmtEntityID := range veipInstKeys {
1259 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1260 "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301261 dh.addUniPort(mgmtEntityID, i, uniVEIP)
Himani Chawla26e555c2020-08-31 12:30:20 +05301262 i++
1263 }
1264 } else {
1265 logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
1266 }
1267 if i == 0 {
1268 logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
1269 }
1270
1271 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1272 * left the code here as comment in case such processing should prove needed unexpectedly
1273 // Init Uni Ports to Admin locked state
1274 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1275 // *** should generate UniLockStateDone event *****
1276 if dh.pLockStateFsm == nil {
1277 dh.createUniLockFsm(true, UniLockStateDone)
1278 } else { //LockStateFSM already init
1279 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1280 dh.runUniLockFsm(true)
1281 }
1282 }
1283 case UniLockStateDone:
1284 {
1285 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
1286 * lockState processing commented out
1287 */
1288 /* Mib download procedure -
1289 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1290 */
1291 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1292 if pMibDlFsm != nil {
1293 if pMibDlFsm.Is(dlStDisabled) {
1294 if err := pMibDlFsm.Event(dlEvStart); err != nil {
1295 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1296 // maybe try a FSM reset and then again ... - TODO!!!
1297 } else {
1298 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1299 // maybe use more specific states here for the specific download steps ...
1300 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
1301 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1302 } else {
1303 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1304 //Begin MIB data download (running autonomously)
1305 }
1306 }
1307 } else {
1308 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1309 // maybe try a FSM reset and then again ... - TODO!!!
1310 }
1311 /***** Mib download started */
1312 } else {
1313 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
1314 }
1315}
1316
Himani Chawla6d2ae152020-09-02 13:11:20 +05301317func (dh *deviceHandler) processMibDownloadDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301318 logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
1319 //initiate DevStateUpdate
1320 if !dh.reconciling {
1321 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1322 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1323 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1324 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1325 } else {
1326 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
1327 }
1328 } else {
1329 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
1330 log.Fields{"device-id": dh.deviceID})
1331 }
1332 if !dh.reconciling {
1333 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1334 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1335 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1336 log.Fields{"device-id": dh.deviceID, "error": err})
1337 } else {
1338 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
1339 }
1340 } else {
1341 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
1342 log.Fields{"device-id": dh.deviceID})
1343 }
1344 //set internal state anyway - as it was done
1345 dh.deviceReason = "initial-mib-downloaded"
1346 // *** should generate UniUnlockStateDone event *****
1347 if dh.pUnlockStateFsm == nil {
1348 dh.createUniLockFsm(false, UniUnlockStateDone)
1349 } else { //UnlockStateFSM already init
Himani Chawla6d2ae152020-09-02 13:11:20 +05301350 dh.pUnlockStateFsm.setSuccessEvent(UniUnlockStateDone)
Himani Chawla26e555c2020-08-31 12:30:20 +05301351 dh.runUniLockFsm(false)
1352 }
1353}
1354
Himani Chawla6d2ae152020-09-02 13:11:20 +05301355func (dh *deviceHandler) processUniUnlockStateDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301356 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
1357
1358 if !dh.reconciling {
1359 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
1360 raisedTs := time.Now().UnixNano()
1361 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1362 } else {
1363 logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
1364 log.Fields{"device-id": dh.deviceID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301365 go dh.reconcileDeviceTechProf()
Himani Chawla26e555c2020-08-31 12:30:20 +05301366 //TODO: further actions e.g. restore flows, metrics, ...
1367 }
1368}
1369
Himani Chawla6d2ae152020-09-02 13:11:20 +05301370func (dh *deviceHandler) processOmciAniConfigDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301371 logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
1372 // attention: the device reason update is done based on ONU-UNI-Port related activity
1373 // - which may cause some inconsistency
1374 if dh.deviceReason != "tech-profile-config-download-success" {
1375 // which may be the case from some previous actvity on another UNI Port of the ONU
1376 if !dh.reconciling {
1377 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1378 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1379 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1380 log.Fields{"device-id": dh.deviceID, "error": err})
1381 } else {
1382 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1383 log.Fields{"device-id": dh.deviceID})
1384 }
1385 } else {
1386 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
1387 log.Fields{"device-id": dh.deviceID})
1388 }
1389 //set internal state anyway - as it was done
1390 dh.deviceReason = "tech-profile-config-download-success"
1391 }
1392}
1393
Himani Chawla6d2ae152020-09-02 13:11:20 +05301394func (dh *deviceHandler) processOmciVlanFilterDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301395 logger.Debugw("OmciVlanFilterDone event received",
1396 log.Fields{"device-id": dh.deviceID})
1397 // attention: the device reason update is done based on ONU-UNI-Port related activity
1398 // - which may cause some inconsistency
1399 // yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
1400
1401 if dh.deviceReason != "omci-flows-pushed" {
1402 // which may be the case from some previous actvity on another UNI Port of the ONU
1403 // or even some previous flow add activity on the same port
1404 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
1405 logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
1406 log.Fields{"device-id": dh.deviceID, "error": err})
1407 } else {
1408 logger.Infow("updated dev reason to ''omci-flows-pushed'",
1409 log.Fields{"device-id": dh.deviceID})
1410 }
1411 //set internal state anyway - as it was done
1412 dh.deviceReason = "omci-flows-pushed"
1413 }
1414}
1415
Himani Chawla6d2ae152020-09-02 13:11:20 +05301416//deviceProcStatusUpdate evaluates possible processing events and initiates according next activities
1417func (dh *deviceHandler) deviceProcStatusUpdate(devEvent OnuDeviceEvent) {
Himani Chawla4d908332020-08-31 12:30:20 +05301418 switch devEvent {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001419 case MibDatabaseSync:
1420 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301421 dh.processMibDatabaseSyncEvent(devEvent)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001422 }
1423 case MibDownloadDone:
1424 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301425 dh.processMibDownloadDoneEvent(devEvent)
1426
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001427 }
1428 case UniUnlockStateDone:
1429 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301430 dh.processUniUnlockStateDoneEvent(devEvent)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001431
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001432 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001433 case OmciAniConfigDone:
1434 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301435 dh.processOmciAniConfigDoneEvent(devEvent)
1436
mpagenko3dbcdd22020-07-22 07:38:45 +00001437 }
mpagenkodff5dda2020-08-28 11:52:01 +00001438 case OmciVlanFilterDone:
1439 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301440 dh.processOmciVlanFilterDoneEvent(devEvent)
mpagenkodff5dda2020-08-28 11:52:01 +00001441
mpagenkodff5dda2020-08-28 11:52:01 +00001442 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001443 default:
1444 {
Himani Chawla4d908332020-08-31 12:30:20 +05301445 logger.Warnw("unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": devEvent})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001446 }
1447 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001448}
1449
Himani Chawla6d2ae152020-09-02 13:11:20 +05301450func (dh *deviceHandler) addUniPort(aUniInstNo uint16, aUniID uint8, aPortType uniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001451 // parameters are IntfId, OnuId, uniId
Himani Chawla6d2ae152020-09-02 13:11:20 +05301452 uniNo := mkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
Himani Chawla4d908332020-08-31 12:30:20 +05301453 uint32(aUniID))
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001454 if _, present := dh.uniEntityMap[uniNo]; present {
Himani Chawla4d908332020-08-31 12:30:20 +05301455 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001456 } else {
Himani Chawla4d908332020-08-31 12:30:20 +05301457 //with arguments aUniID, a_portNo, aPortType
Himani Chawla6d2ae152020-09-02 13:11:20 +05301458 pUniPort := newOnuUniPort(aUniID, uniNo, aUniInstNo, aPortType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001459 if pUniPort == nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301460 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001461 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001462 //store UniPort with the System-PortNumber key
1463 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001464 if !dh.reconciling {
1465 // create announce the UniPort to the core as VOLTHA Port object
Himani Chawla6d2ae152020-09-02 13:11:20 +05301466 if err := pUniPort.createVolthaPort(dh); err == nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001467 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1468 } //error logging already within UniPort method
1469 } else {
1470 logger.Debugw("reconciling - onuUniPort already added", log.Fields{"for PortNo": uniNo, "device-id": dh.deviceID})
1471 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001472 }
1473 }
1474}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001475
mpagenko3af1f032020-06-10 08:53:41 +00001476// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05301477func (dh *deviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001478 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
Himani Chawla4d908332020-08-31 12:30:20 +05301479 // but towards core only the first port active state is signaled
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001480 // with following remark:
1481 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1482 // # load on the core
1483
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001484 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001485
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001486 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001487 // only if this port is validated for operState transfer
Himani Chawla6d2ae152020-09-02 13:11:20 +05301488 if (1<<uniPort.uniID)&activeUniPortStateUpdateMask == (1 << uniPort.uniID) {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001489 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301490 uniPort.setOperState(vc.OperStatus_ACTIVE)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001491 if !dh.reconciling {
1492 //maybe also use getter functions on uniPort - perhaps later ...
1493 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1494 } else {
1495 logger.Debugw("reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
1496 }
mpagenko3af1f032020-06-10 08:53:41 +00001497 }
1498 }
1499}
1500
1501// Disable UniPortState and update core port state accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05301502func (dh *deviceHandler) disableUniPortStateUpdate() {
mpagenko3af1f032020-06-10 08:53:41 +00001503 // compare enableUniPortStateUpdate() above
1504 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1505 for uniNo, uniPort := range dh.uniEntityMap {
1506 // only if this port is validated for operState transfer
Himani Chawla6d2ae152020-09-02 13:11:20 +05301507 if (1<<uniPort.uniID)&activeUniPortStateUpdateMask == (1 << uniPort.uniID) {
mpagenko3af1f032020-06-10 08:53:41 +00001508 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301509 uniPort.setOperState(vc.OperStatus_UNKNOWN)
mpagenko3af1f032020-06-10 08:53:41 +00001510 //maybe also use getter functions on uniPort - perhaps later ...
1511 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001512 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001513 }
1514}
1515
1516// ONU_Active/Inactive announcement on system KAFKA bus
1517// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
Himani Chawla6d2ae152020-09-02 13:11:20 +05301518func (dh *deviceHandler) sendOnuOperStateEvent(aOperState vc.OperStatus_Types, aDeviceID string, raisedTs int64) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001519 var de voltha.DeviceEvent
1520 eventContext := make(map[string]string)
1521 //Populating event context
1522 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
Himani Chawla4d908332020-08-31 12:30:20 +05301523 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentID, dh.parentID)
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001524 if err != nil || parentDevice == nil {
1525 logger.Errorw("Failed to fetch parent device for OnuEvent",
Himani Chawla4d908332020-08-31 12:30:20 +05301526 log.Fields{"parentID": dh.parentID, "err": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001527 }
1528 oltSerialNumber := parentDevice.SerialNumber
1529
1530 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1531 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1532 eventContext["serial-number"] = dh.device.SerialNumber
1533 eventContext["olt_serial_number"] = oltSerialNumber
Himani Chawla4d908332020-08-31 12:30:20 +05301534 eventContext["device_id"] = aDeviceID
1535 eventContext["registration_id"] = aDeviceID //py: string(device_id)??
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001536 logger.Debugw("prepare ONU_ACTIVATED event",
Himani Chawla4d908332020-08-31 12:30:20 +05301537 log.Fields{"DeviceId": aDeviceID, "EventContext": eventContext})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001538
1539 /* Populating device event body */
1540 de.Context = eventContext
Himani Chawla4d908332020-08-31 12:30:20 +05301541 de.ResourceId = aDeviceID
1542 if aOperState == voltha.OperStatus_ACTIVE {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001543 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1544 de.Description = fmt.Sprintf("%s Event - %s - %s",
1545 cEventObjectType, cOnuActivatedEvent, "Raised")
1546 } else {
1547 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1548 de.Description = fmt.Sprintf("%s Event - %s - %s",
1549 cEventObjectType, cOnuActivatedEvent, "Cleared")
1550 }
1551 /* Send event to KAFKA */
1552 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1553 logger.Warnw("could not send ONU_ACTIVATED event",
Himani Chawla4d908332020-08-31 12:30:20 +05301554 log.Fields{"device-id": aDeviceID, "error": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001555 }
1556 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
Himani Chawla4d908332020-08-31 12:30:20 +05301557 log.Fields{"device-id": aDeviceID, "with-EventName": de.DeviceEventName})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001558}
1559
Himani Chawla4d908332020-08-31 12:30:20 +05301560// createUniLockFsm initializes and runs the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Himani Chawla6d2ae152020-09-02 13:11:20 +05301561func (dh *deviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001562 chLSFsm := make(chan Message, 2048)
1563 var sFsmName string
Himani Chawla4d908332020-08-31 12:30:20 +05301564 if aAdminState {
divyadesai4d299552020-08-18 07:13:49 +00001565 logger.Infow("createLockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001566 sFsmName = "LockStateFSM"
1567 } else {
divyadesai4d299552020-08-18 07:13:49 +00001568 logger.Infow("createUnlockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001569 sFsmName = "UnLockStateFSM"
1570 }
mpagenko3af1f032020-06-10 08:53:41 +00001571
Himani Chawla6d2ae152020-09-02 13:11:20 +05301572 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenko3af1f032020-06-10 08:53:41 +00001573 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001574 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001575 return
1576 }
Himani Chawla6d2ae152020-09-02 13:11:20 +05301577 pLSFsm := newLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001578 sFsmName, dh.deviceID, chLSFsm)
1579 if pLSFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301580 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001581 dh.pLockStateFsm = pLSFsm
1582 } else {
1583 dh.pUnlockStateFsm = pLSFsm
1584 }
1585 dh.runUniLockFsm(aAdminState)
1586 } else {
divyadesai4d299552020-08-18 07:13:49 +00001587 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001588 }
1589}
1590
1591// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Himani Chawla6d2ae152020-09-02 13:11:20 +05301592func (dh *deviceHandler) runUniLockFsm(aAdminState bool) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001593 /* Uni Port lock/unlock procedure -
1594 ***** should run via 'adminDone' state and generate the argument requested event *****
1595 */
1596 var pLSStatemachine *fsm.FSM
Himani Chawla4d908332020-08-31 12:30:20 +05301597 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001598 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1599 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1600 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001601 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301602 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001603 }
1604 } else {
1605 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1606 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1607 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001608 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301609 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001610 }
1611 }
1612 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001613 if pLSStatemachine.Is(uniStDisabled) {
1614 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001615 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1616 // maybe try a FSM reset and then again ... - TODO!!!
1617 } else {
1618 /***** LockStateFSM started */
1619 logger.Debugw("LockStateFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001620 "state": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001621 }
1622 } else {
1623 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001624 "have": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001625 // maybe try a FSM reset and then again ... - TODO!!!
1626 }
1627 } else {
divyadesai4d299552020-08-18 07:13:49 +00001628 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001629 // maybe try a FSM reset and then again ... - TODO!!!
1630 }
1631}
1632
Himani Chawla6d2ae152020-09-02 13:11:20 +05301633//setBackend provides a DB backend for the specified path on the existing KV client
1634func (dh *deviceHandler) setBackend(aBasePathKvStore string) *db.Backend {
mpagenkoaf801632020-07-03 10:00:42 +00001635 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1636 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
divyadesai4d299552020-08-18 07:13:49 +00001637 "BasePathKvStore": aBasePathKvStore, "device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +00001638 kvbackend := &db.Backend{
1639 Client: dh.pOpenOnuAc.kvClient,
1640 StoreType: dh.pOpenOnuAc.KVStoreType,
1641 /* address config update acc. to [VOL-2736] */
1642 Address: addr,
1643 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1644 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001645
mpagenkoaf801632020-07-03 10:00:42 +00001646 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001647}
Himani Chawla6d2ae152020-09-02 13:11:20 +05301648func (dh *deviceHandler) getFlowOfbFields(apFlowItem *ofp.OfpFlowStats, loMatchVlan *uint16,
Himani Chawla26e555c2020-08-31 12:30:20 +05301649 loAddPcp *uint8, loIPProto *uint32) {
mpagenkodff5dda2020-08-28 11:52:01 +00001650
mpagenkodff5dda2020-08-28 11:52:01 +00001651 for _, field := range flow.GetOfbFields(apFlowItem) {
1652 switch field.Type {
1653 case of.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
1654 {
1655 logger.Debugw("FlowAdd type EthType", log.Fields{"device-id": dh.deviceID,
1656 "EthType": strconv.FormatInt(int64(field.GetEthType()), 16)})
1657 }
1658 case of.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
1659 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301660 *loIPProto = field.GetIpProto()
mpagenkodff5dda2020-08-28 11:52:01 +00001661 logger.Debugw("FlowAdd type IpProto", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301662 "IpProto": strconv.FormatInt(int64(*loIPProto), 16)})
1663 if *loIPProto == 2 {
mpagenkodff5dda2020-08-28 11:52:01 +00001664 // some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
1665 // avoids installing invalid EVTOCD rule
1666 logger.Debugw("FlowAdd type IpProto 2: TT workaround: ignore flow",
1667 log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301668 "IpProto": strconv.FormatInt(int64(*loIPProto), 16)})
1669 return
mpagenkodff5dda2020-08-28 11:52:01 +00001670 }
1671 }
1672 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
1673 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301674 *loMatchVlan = uint16(field.GetVlanVid())
mpagenkodff5dda2020-08-28 11:52:01 +00001675 loMatchVlanMask := uint16(field.GetVlanVidMask())
Himani Chawla26e555c2020-08-31 12:30:20 +05301676 if !(*loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) &&
mpagenkodff5dda2020-08-28 11:52:01 +00001677 loMatchVlanMask == uint16(of.OfpVlanId_OFPVID_PRESENT)) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301678 *loMatchVlan = *loMatchVlan & 0xFFF // not transparent: copy only ID bits
mpagenkodff5dda2020-08-28 11:52:01 +00001679 }
1680 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301681 "VID": strconv.FormatInt(int64(*loMatchVlan), 16)})
mpagenkodff5dda2020-08-28 11:52:01 +00001682 }
1683 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
1684 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301685 *loAddPcp = uint8(field.GetVlanPcp())
mpagenkodff5dda2020-08-28 11:52:01 +00001686 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1687 "PCP": loAddPcp})
1688 }
1689 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
1690 {
1691 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1692 "UDP-DST": strconv.FormatInt(int64(field.GetUdpDst()), 16)})
1693 }
1694 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
1695 {
1696 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1697 "UDP-SRC": strconv.FormatInt(int64(field.GetUdpSrc()), 16)})
1698 }
1699 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
1700 {
1701 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1702 "IPv4-DST": field.GetIpv4Dst()})
1703 }
1704 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC:
1705 {
1706 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1707 "IPv4-SRC": field.GetIpv4Src()})
1708 }
1709 case of.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
1710 {
1711 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1712 "Metadata": field.GetTableMetadata()})
1713 }
1714 /*
1715 default:
1716 {
1717 //all other entires ignored
1718 }
1719 */
1720 }
1721 } //for all OfbFields
Himani Chawla26e555c2020-08-31 12:30:20 +05301722}
mpagenkodff5dda2020-08-28 11:52:01 +00001723
Himani Chawla6d2ae152020-09-02 13:11:20 +05301724func (dh *deviceHandler) getFlowActions(apFlowItem *ofp.OfpFlowStats, loSetPcp *uint8, loSetVlan *uint16) {
mpagenkodff5dda2020-08-28 11:52:01 +00001725 for _, action := range flow.GetActions(apFlowItem) {
1726 switch action.Type {
1727 /* not used:
1728 case of.OfpActionType_OFPAT_OUTPUT:
1729 {
1730 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1731 "Output": action.GetOutput()})
1732 }
1733 */
1734 case of.OfpActionType_OFPAT_PUSH_VLAN:
1735 {
1736 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1737 "PushEthType": strconv.FormatInt(int64(action.GetPush().Ethertype), 16)})
1738 }
1739 case of.OfpActionType_OFPAT_SET_FIELD:
1740 {
1741 pActionSetField := action.GetSetField()
1742 if pActionSetField.Field.OxmClass != of.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1743 logger.Warnw("FlowAdd action SetField invalid OxmClass (ignored)", log.Fields{"device-id": dh.deviceID,
1744 "OxcmClass": pActionSetField.Field.OxmClass})
1745 }
1746 if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Himani Chawla26e555c2020-08-31 12:30:20 +05301747 *loSetVlan = uint16(pActionSetField.Field.GetOfbField().GetVlanVid())
mpagenkodff5dda2020-08-28 11:52:01 +00001748 logger.Debugw("FlowAdd Set VLAN from SetField action", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301749 "SetVlan": strconv.FormatInt(int64(*loSetVlan), 16)})
mpagenkodff5dda2020-08-28 11:52:01 +00001750 } else if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
Himani Chawla26e555c2020-08-31 12:30:20 +05301751 *loSetPcp = uint8(pActionSetField.Field.GetOfbField().GetVlanPcp())
mpagenkodff5dda2020-08-28 11:52:01 +00001752 logger.Debugw("FlowAdd Set PCP from SetField action", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301753 "SetPcp": *loSetPcp})
mpagenkodff5dda2020-08-28 11:52:01 +00001754 } else {
1755 logger.Warnw("FlowAdd action SetField invalid FieldType", log.Fields{"device-id": dh.deviceID,
1756 "Type": pActionSetField.Field.GetOfbField().Type})
1757 }
1758 }
1759 /*
1760 default:
1761 {
1762 //all other entires ignored
1763 }
1764 */
1765 }
1766 } //for all Actions
Himani Chawla26e555c2020-08-31 12:30:20 +05301767}
1768
1769//addFlowItemToUniPort parses the actual flow item to add it to the UniPort
Himani Chawla6d2ae152020-09-02 13:11:20 +05301770func (dh *deviceHandler) addFlowItemToUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *onuUniPort) error {
Himani Chawla26e555c2020-08-31 12:30:20 +05301771 var loSetVlan uint16 = uint16(of.OfpVlanId_OFPVID_NONE) //noValidEntry
1772 var loMatchVlan uint16 = uint16(of.OfpVlanId_OFPVID_PRESENT) //reserved VLANID entry
1773 var loAddPcp, loSetPcp uint8
1774 var loIPProto uint32
1775 /* the TechProfileId is part of the flow Metadata - compare also comment within
1776 * OLT-Adapter:openolt_flowmgr.go
1777 * Metadata 8 bytes:
1778 * Most Significant 2 Bytes = Inner VLAN
1779 * Next 2 Bytes = Tech Profile ID(TPID)
1780 * Least Significant 4 Bytes = Port ID
1781 * Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1782 * subscriber related flows.
1783 */
1784
1785 metadata := flow.GetMetadataFromWriteMetadataAction(apFlowItem)
1786 if metadata == 0 {
1787 logger.Debugw("FlowAdd invalid metadata - abort",
1788 log.Fields{"device-id": dh.deviceID})
1789 return errors.New("flowAdd invalid metadata")
1790 }
1791 loTpID := flow.GetTechProfileIDFromWriteMetaData(metadata)
1792 logger.Debugw("FlowAdd TechProfileId", log.Fields{"device-id": dh.deviceID, "TP-Id": loTpID})
1793
1794 dh.getFlowOfbFields(apFlowItem, &loMatchVlan, &loAddPcp, &loIPProto)
1795 if loIPProto == 2 {
1796 // 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,
1800 "IpProto": strconv.FormatInt(int64(loIPProto), 16)})
1801 return nil
1802 }
1803 dh.getFlowActions(apFlowItem, &loSetPcp, &loSetVlan)
mpagenkodff5dda2020-08-28 11:52:01 +00001804
1805 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1806 logger.Errorw("FlowAdd aborted - SetVlanId undefined, but MatchVid set", log.Fields{
1807 "device-id": dh.deviceID, "UniPort": apUniPort.portNo,
1808 "set_vid": strconv.FormatInt(int64(loSetVlan), 16),
1809 "match_vid": strconv.FormatInt(int64(loMatchVlan), 16)})
1810 //TODO!!: Use DeviceId within the error response to rwCore
1811 // likewise also in other error response cases to calling components as requested in [VOL-3458]
Himani Chawla26e555c2020-08-31 12:30:20 +05301812 return errors.New("flowAdd Set/Match VlanId inconsistent")
mpagenkodff5dda2020-08-28 11:52:01 +00001813 }
1814 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) {
1815 logger.Debugw("FlowAdd vlan-any/copy", log.Fields{"device-id": dh.deviceID})
1816 loSetVlan = loMatchVlan //both 'transparent' (copy any)
1817 } else {
1818 //looks like OMCI value 4097 (copyFromOuter - for Uni double tagged) is not supported here
1819 if loSetVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1820 // not set to transparent
Himani Chawla26e555c2020-08-31 12:30:20 +05301821 loSetVlan &= 0x0FFF //mask VID bits as prerequisite for vlanConfigFsm
mpagenkodff5dda2020-08-28 11:52:01 +00001822 }
1823 logger.Debugw("FlowAdd vlan-set", log.Fields{"device-id": dh.deviceID})
1824 }
1825 //TODO!!: further FlowAdd requests may be valid even in case the FSM is already running,
1826 // e.g. for multi-step flow configuration, error treatment must be redefined in this context as requested in [VOL-3441]
Himani Chawla26e555c2020-08-31 12:30:20 +05301827 if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
mpagenkodff5dda2020-08-28 11:52:01 +00001828 logger.Errorw("FlowAdd aborted - FSM already running", log.Fields{
1829 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
Himani Chawla26e555c2020-08-31 12:30:20 +05301830 return errors.New("flowAdd FSM already running")
mpagenkodff5dda2020-08-28 11:52:01 +00001831 }
1832 return dh.createVlanFilterFsm(apUniPort,
1833 loTpID, loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterDone)
1834}
1835
Himani Chawla26e555c2020-08-31 12:30:20 +05301836// createVlanFilterFsm initializes and runs the VlanFilter FSM to transfer OMCI related VLAN config
Himani Chawla6d2ae152020-09-02 13:11:20 +05301837func (dh *deviceHandler) createVlanFilterFsm(apUniPort *onuUniPort,
mpagenkodff5dda2020-08-28 11:52:01 +00001838 aTpID uint16, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8, aDevEvent OnuDeviceEvent) error {
1839 chVlanFilterFsm := make(chan Message, 2048)
1840
Himani Chawla6d2ae152020-09-02 13:11:20 +05301841 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenkodff5dda2020-08-28 11:52:01 +00001842 if pDevEntry == nil {
1843 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301844 return fmt.Errorf("no valid OnuDevice for device-id %x - aborting", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001845 }
1846
1847 pVlanFilterFsm := NewUniVlanConfigFsm(dh, pDevEntry.PDevOmciCC, apUniPort, dh.pOnuTP,
1848 pDevEntry.pOnuDB, aTpID, aDevEvent, "UniVlanConfigFsm", dh.deviceID, chVlanFilterFsm,
1849 dh.pOpenOnuAc.AcceptIncrementalEvto, aMatchVlan, aSetVlan, aSetPcp)
1850 if pVlanFilterFsm != nil {
Himani Chawla26e555c2020-08-31 12:30:20 +05301851 dh.UniVlanConfigFsmMap[apUniPort.uniID] = pVlanFilterFsm
mpagenkodff5dda2020-08-28 11:52:01 +00001852 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1853 if pVlanFilterStatemachine != nil {
1854 if pVlanFilterStatemachine.Is(vlanStDisabled) {
1855 if err := pVlanFilterStatemachine.Event(vlanEvStart); err != nil {
1856 logger.Warnw("UniVlanConfigFsm: can't start", log.Fields{"err": err})
Himani Chawla26e555c2020-08-31 12:30:20 +05301857 return fmt.Errorf("can't start UniVlanConfigFsm for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001858 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301859 /***** UniVlanConfigFsm started */
1860 logger.Debugw("UniVlanConfigFsm started", log.Fields{
1861 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
1862 "UniPort": apUniPort.portNo})
mpagenkodff5dda2020-08-28 11:52:01 +00001863 } else {
1864 logger.Warnw("wrong state of UniVlanConfigFsm - want: disabled", log.Fields{
1865 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301866 return fmt.Errorf("uniVlanConfigFsm not in expected disabled state for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001867 }
1868 } else {
1869 logger.Errorw("UniVlanConfigFsm StateMachine invalid - cannot be executed!!", log.Fields{
1870 "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301871 return fmt.Errorf("uniVlanConfigFsm invalid for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001872 }
1873 } else {
1874 logger.Errorw("UniVlanConfigFsm could not be created - abort!!", log.Fields{
1875 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
Himani Chawla26e555c2020-08-31 12:30:20 +05301876 return fmt.Errorf("uniVlanConfigFsm could not be created for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001877 }
1878 return nil
1879}
1880
1881//verifyUniVlanConfigRequest checks on existence of flow configuration and starts it accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05301882func (dh *deviceHandler) verifyUniVlanConfigRequest(apUniPort *onuUniPort) {
mpagenkodff5dda2020-08-28 11:52:01 +00001883 //TODO!! verify and start pending flow configuration
1884 //some pending config request my exist in case the UniVlanConfig FSM was already started - with internal data -
1885 //but execution was set to 'on hold' as first the TechProfile config had to be applied
Himani Chawla26e555c2020-08-31 12:30:20 +05301886 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
mpagenkodff5dda2020-08-28 11:52:01 +00001887 //VlanFilterFsm exists and was already started (assumed to wait for TechProfile execution here)
1888 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1889 if pVlanFilterStatemachine != nil {
1890 if pVlanFilterStatemachine.Is(vlanStWaitingTechProf) {
1891 if err := pVlanFilterStatemachine.Event(vlanEvContinueConfig); err != nil {
1892 logger.Warnw("UniVlanConfigFsm: can't continue processing", log.Fields{"err": err})
1893 } else {
1894 /***** UniVlanConfigFsm continued */
1895 logger.Debugw("UniVlanConfigFsm continued", log.Fields{
1896 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
1897 "UniPort": apUniPort.portNo})
1898 }
1899 } else {
1900 logger.Debugw("no state of UniVlanConfigFsm to be continued", log.Fields{
1901 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
1902 }
1903 } else {
1904 logger.Debugw("UniVlanConfigFsm StateMachine does not exist, no flow processing", log.Fields{
1905 "device-id": dh.deviceID})
1906 }
1907
1908 } // else: nothing to do
1909}
1910
1911//RemoveVlanFilterFsm deletes the stored pointer to the VlanConfigFsm
1912// 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 +05301913func (dh *deviceHandler) RemoveVlanFilterFsm(apUniPort *onuUniPort) {
mpagenkodff5dda2020-08-28 11:52:01 +00001914 logger.Debugw("remove UniVlanConfigFsm StateMachine", log.Fields{
1915 "device-id": dh.deviceID, "uniPort": apUniPort.portNo})
1916 //save to do, even if entry dows not exist
Himani Chawla26e555c2020-08-31 12:30:20 +05301917 delete(dh.UniVlanConfigFsmMap, apUniPort.uniID)
mpagenkodff5dda2020-08-28 11:52:01 +00001918}