blob: 054a0bbdbc81b7c58ced1a30dc00cea78b299d7f [file] [log] [blame]
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
22 "encoding/hex"
23 "errors"
24 "fmt"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000025 "strconv"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000026 "sync"
27 "time"
28
29 "github.com/gogo/protobuf/proto"
30 "github.com/golang/protobuf/ptypes"
31 "github.com/looplab/fsm"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +000032 me "github.com/opencord/omci-lib-go/generated"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000033 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
mpagenkoaf801632020-07-03 10:00:42 +000034 "github.com/opencord/voltha-lib-go/v3/pkg/db"
mpagenkodff5dda2020-08-28 11:52:01 +000035 flow "github.com/opencord/voltha-lib-go/v3/pkg/flows"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000036 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000037 vc "github.com/opencord/voltha-protos/v3/go/common"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000038 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
mpagenkodff5dda2020-08-28 11:52:01 +000039 "github.com/opencord/voltha-protos/v3/go/openflow_13"
40 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
41 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000042 oop "github.com/opencord/voltha-protos/v3/go/openolt"
43 "github.com/opencord/voltha-protos/v3/go/voltha"
44)
45
46/*
47// Constants for number of retries and for timeout
48const (
49 MaxRetry = 10
50 MaxTimeOutInMs = 500
51)
52*/
53
mpagenko1cc3cb42020-07-27 15:24:38 +000054const (
55 // events of Device FSM
56 devEvDeviceInit = "devEvDeviceInit"
57 devEvGrpcConnected = "devEvGrpcConnected"
58 devEvGrpcDisconnected = "devEvGrpcDisconnected"
59 devEvDeviceUpInd = "devEvDeviceUpInd"
60 devEvDeviceDownInd = "devEvDeviceDownInd"
61)
62const (
63 // states of Device FSM
64 devStNull = "devStNull"
65 devStDown = "devStDown"
66 devStInit = "devStInit"
67 devStConnected = "devStConnected"
68 devStUp = "devStUp"
69)
70
Holger Hildebrandt24d51952020-05-04 14:03:42 +000071//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
72const (
Himani Chawla4d908332020-08-31 12:30:20 +053073 pon = voltha.EventSubCategory_PON
74 //olt = voltha.EventSubCategory_OLT
75 //ont = voltha.EventSubCategory_ONT
76 //onu = voltha.EventSubCategory_ONU
77 //nni = voltha.EventSubCategory_NNI
78 //service = voltha.EventCategory_SERVICE
79 //security = voltha.EventCategory_SECURITY
80 equipment = voltha.EventCategory_EQUIPMENT
81 //processing = voltha.EventCategory_PROCESSING
82 //environment = voltha.EventCategory_ENVIRONMENT
83 //communication = voltha.EventCategory_COMMUNICATION
Holger Hildebrandt24d51952020-05-04 14:03:42 +000084)
85
86const (
87 cEventObjectType = "ONU"
88)
89const (
90 cOnuActivatedEvent = "ONU_ACTIVATED"
91)
92
Himani Chawla6d2ae152020-09-02 13:11:20 +053093//deviceHandler will interact with the ONU ? device.
94type deviceHandler struct {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000095 deviceID string
96 DeviceType string
97 adminState string
98 device *voltha.Device
99 logicalDeviceID string
100 ProxyAddressID string
101 ProxyAddressType string
Himani Chawla4d908332020-08-31 12:30:20 +0530102 parentID string
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000103 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000104
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000105 coreProxy adapterif.CoreProxy
106 AdapterProxy adapterif.AdapterProxy
107 EventProxy adapterif.EventProxy
108
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000109 pOpenOnuAc *OpenONUAC
110 pDeviceStateFsm *fsm.FSM
Himani Chawla4d908332020-08-31 12:30:20 +0530111 //pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +0000112 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000113 pOnuOmciDevice *OnuDeviceEntry
Himani Chawla6d2ae152020-09-02 13:11:20 +0530114 pOnuTP *onuUniTechProf
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000115 exitChannel chan int
116 lockDevice sync.RWMutex
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000117 pOnuIndication *oop.OnuIndication
mpagenko3af1f032020-06-10 08:53:41 +0000118 deviceReason string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530119 pLockStateFsm *lockStateFsm
120 pUnlockStateFsm *lockStateFsm
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000121
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000122 //flowMgr *OpenOltFlowMgr
123 //eventMgr *OpenOltEventMgr
124 //resourceMgr *rsrcMgr.OpenOltResourceMgr
125
126 //discOnus sync.Map
127 //onus sync.Map
128 //portStats *OpenOltStatisticsMgr
129 //metrics *pmmetrics.PmMetrics
mpagenkodff5dda2020-08-28 11:52:01 +0000130 stopCollector chan bool
131 stopHeartbeatCheck chan bool
132 activePorts sync.Map
Himani Chawla6d2ae152020-09-02 13:11:20 +0530133 uniEntityMap map[uint32]*onuUniPort
mpagenkodff5dda2020-08-28 11:52:01 +0000134 UniVlanConfigFsmMap map[uint8]*UniVlanConfigFsm
135 reconciling bool
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000136}
137
Himani Chawla6d2ae152020-09-02 13:11:20 +0530138//newDeviceHandler creates a new device handler
139func newDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenONUAC) *deviceHandler {
140 var dh deviceHandler
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000141 dh.coreProxy = cp
142 dh.AdapterProxy = ap
143 dh.EventProxy = ep
144 cloned := (proto.Clone(device)).(*voltha.Device)
145 dh.deviceID = cloned.Id
146 dh.DeviceType = cloned.Type
147 dh.adminState = "up"
148 dh.device = cloned
149 dh.pOpenOnuAc = adapter
150 dh.exitChannel = make(chan int, 1)
151 dh.lockDevice = sync.RWMutex{}
mpagenko3af1f032020-06-10 08:53:41 +0000152 dh.deviceEntrySet = make(chan bool, 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000153 dh.stopCollector = make(chan bool, 2)
154 dh.stopHeartbeatCheck = make(chan bool, 2)
155 //dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
156 dh.activePorts = sync.Map{}
157 //TODO initialize the support classes.
Himani Chawla6d2ae152020-09-02 13:11:20 +0530158 dh.uniEntityMap = make(map[uint32]*onuUniPort)
mpagenkodff5dda2020-08-28 11:52:01 +0000159 dh.UniVlanConfigFsmMap = make(map[uint8]*UniVlanConfigFsm)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000160 dh.reconciling = false
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000161
162 // Device related state machine
163 dh.pDeviceStateFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000164 devStNull,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000165 fsm.Events{
mpagenko1cc3cb42020-07-27 15:24:38 +0000166 {Name: devEvDeviceInit, Src: []string{devStNull, devStDown}, Dst: devStInit},
167 {Name: devEvGrpcConnected, Src: []string{devStInit}, Dst: devStConnected},
168 {Name: devEvGrpcDisconnected, Src: []string{devStConnected, devStDown}, Dst: devStInit},
169 {Name: devEvDeviceUpInd, Src: []string{devStConnected, devStDown}, Dst: devStUp},
170 {Name: devEvDeviceDownInd, Src: []string{devStUp}, Dst: devStDown},
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000171 },
172 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000173 "before_event": func(e *fsm.Event) { dh.logStateChange(e) },
174 ("before_" + devEvDeviceInit): func(e *fsm.Event) { dh.doStateInit(e) },
175 ("after_" + devEvDeviceInit): func(e *fsm.Event) { dh.postInit(e) },
176 ("before_" + devEvGrpcConnected): func(e *fsm.Event) { dh.doStateConnected(e) },
177 ("before_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.doStateInit(e) },
178 ("after_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.postInit(e) },
179 ("before_" + devEvDeviceUpInd): func(e *fsm.Event) { dh.doStateUp(e) },
180 ("before_" + devEvDeviceDownInd): func(e *fsm.Event) { dh.doStateDown(e) },
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000181 },
182 )
mpagenkoaf801632020-07-03 10:00:42 +0000183
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000184 return &dh
185}
186
Himani Chawla6d2ae152020-09-02 13:11:20 +0530187// start save the device to the data model
188func (dh *deviceHandler) start(ctx context.Context) {
divyadesai4d299552020-08-18 07:13:49 +0000189 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000190 // Add the initial device to the local model
191 logger.Debug("device-handler-started")
192}
193
Himani Chawla4d908332020-08-31 12:30:20 +0530194/*
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000195// stop stops the device dh. Not much to do for now
Himani Chawla6d2ae152020-09-02 13:11:20 +0530196func (dh *deviceHandler) stop(ctx context.Context) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000197 logger.Debug("stopping-device-handler")
198 dh.exitChannel <- 1
199}
Himani Chawla4d908332020-08-31 12:30:20 +0530200*/
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000201
202// ##########################################################################################
Himani Chawla6d2ae152020-09-02 13:11:20 +0530203// deviceHandler methods that implement the adapters interface requests ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000204
Himani Chawla6d2ae152020-09-02 13:11:20 +0530205//adoptOrReconcileDevice adopts the OLT device
206func (dh *deviceHandler) adoptOrReconcileDevice(ctx context.Context, device *voltha.Device) {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000207 logger.Debugw("Adopt_or_reconcile_device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000208
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000209 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
mpagenko1cc3cb42020-07-27 15:24:38 +0000210 if dh.pDeviceStateFsm.Is(devStNull) {
211 if err := dh.pDeviceStateFsm.Event(devEvDeviceInit); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000212 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
213 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000214 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000215 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000216 logger.Debugw("AdoptOrReconcileDevice: Agent/device init already done", log.Fields{"device-id": device.Id})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000217 }
218
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000219}
220
Himani Chawla6d2ae152020-09-02 13:11:20 +0530221func (dh *deviceHandler) processInterAdapterOMCIReqMessage(msg *ic.InterAdapterMessage) error {
Himani Chawla26e555c2020-08-31 12:30:20 +0530222 msgBody := msg.GetBody()
223 omciMsg := &ic.InterAdapterOmciMessage{}
224 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
225 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
226 "device-id": dh.deviceID, "error": err})
227 return err
228 }
229
230 //assuming omci message content is hex coded!
231 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
232 logger.Debugw("inter-adapter-recv-omci", log.Fields{
233 "device-id": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
234 //receive_message(omci_msg.message)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530235 pDevEntry := dh.getOnuDeviceEntry(true)
Himani Chawla26e555c2020-08-31 12:30:20 +0530236 if pDevEntry != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530237 return pDevEntry.PDevOmciCC.receiveMessage(context.TODO(), omciMsg.Message)
Himani Chawla26e555c2020-08-31 12:30:20 +0530238 }
239 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000240 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530241}
242
Himani Chawla6d2ae152020-09-02 13:11:20 +0530243func (dh *deviceHandler) processInterAdapterONUIndReqMessage(msg *ic.InterAdapterMessage) error {
Himani Chawla26e555c2020-08-31 12:30:20 +0530244 msgBody := msg.GetBody()
245 onuIndication := &oop.OnuIndication{}
246 if err := ptypes.UnmarshalAny(msgBody, onuIndication); err != nil {
247 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
248 "device-id": dh.deviceID, "error": err})
249 return err
250 }
251
252 onuOperstate := onuIndication.GetOperState()
mpagenko900ee4b2020-10-12 11:56:34 +0000253 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"device-id": dh.deviceID,
254 "OnuId": onuIndication.GetOnuId(),
Himani Chawla26e555c2020-08-31 12:30:20 +0530255 "AdminState": onuIndication.GetAdminState(), "OperState": onuOperstate,
256 "SNR": onuIndication.GetSerialNumber()})
257
258 //interface related functions might be error checked ....
259 if onuOperstate == "up" {
260 _ = dh.createInterface(onuIndication)
261 } else if (onuOperstate == "down") || (onuOperstate == "unreachable") {
262 _ = dh.updateInterface(onuIndication)
263 } else {
264 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onuIndication.GetOnuId()})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000265 return fmt.Errorf("invalidOperState: %s, %s", onuOperstate, dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530266 }
267 return nil
268}
269
Himani Chawla6d2ae152020-09-02 13:11:20 +0530270func (dh *deviceHandler) processInterAdapterTechProfileDownloadReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530271 msg *ic.InterAdapterMessage) error {
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000272
273 pDevEntry := dh.getOnuDeviceEntry(true)
274 if pDevEntry == nil {
275 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
276 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
277 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530278 if dh.pOnuTP == nil {
279 //should normally not happen ...
280 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
281 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000282 return fmt.Errorf("techProfile DLMsg request while onuTechProf instance not setup: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530283 }
284 if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
285 // I've seen cases for this request, where the device was already stopped
286 logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000287 return fmt.Errorf("device-unreachable: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530288 }
289
290 msgBody := msg.GetBody()
291 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
292 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
293 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
294 "device-id": dh.deviceID, "error": err})
295 return err
296 }
297
298 // we have to lock access to TechProfile processing based on different messageType calls or
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000299 // even to fast subsequent calls of the same messageType as well as OnuKVStore processing due
300 // to possible concurrent access by flow processing
Himani Chawla26e555c2020-08-31 12:30:20 +0530301 dh.pOnuTP.lockTpProcMutex()
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000302 defer dh.pOnuTP.unlockTpProcMutex()
303 pDevEntry.lockOnuKVStoreMutex()
304 defer pDevEntry.unlockOnuKVStoreMutex()
305
306 if techProfMsg.UniId > 255 {
307 return fmt.Errorf(fmt.Sprintf("received UniId value exceeds range: %d, device-id: %s",
308 techProfMsg.UniId, dh.deviceID))
309 }
310 uniID := uint8(techProfMsg.UniId)
311
312 if bTpModify := pDevEntry.updateOnuUniTpPath(uniID, techProfMsg.Path); bTpModify {
Himani Chawla26e555c2020-08-31 12:30:20 +0530313 // if there has been some change for some uni TechProfilePath
314 //in order to allow concurrent calls to other dh instances we do not wait for execution here
315 //but doing so we can not indicate problems to the caller (who does what with that then?)
316 //by now we just assume straightforward successful execution
317 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
318 // possible problems to the caller later autonomously
319
320 // deadline context to ensure completion of background routines waited for
321 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +0530322 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Himani Chawla26e555c2020-08-31 12:30:20 +0530323 dctx, cancel := context.WithDeadline(context.Background(), deadline)
324
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000325 dh.pOnuTP.resetTpProcessingErrorIndication()
326 pDevEntry.resetKvProcessingErrorIndication()
327
Himani Chawla26e555c2020-08-31 12:30:20 +0530328 var wg sync.WaitGroup
329 wg.Add(2) // for the 2 go routines to finish
330 // attention: deadline completion check and wg.Done is to be done in both routines
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000331 go dh.pOnuTP.configureUniTp(dctx, uniID, techProfMsg.Path, &wg)
332 go pDevEntry.updateOnuKvStore(dctx, &wg)
mpagenko01e726e2020-10-23 09:45:29 +0000333 dh.waitForCompletion(cancel, &wg, "TechProfDwld") //wait for background process to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000334
335 return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(), pDevEntry.getKvProcessingErrorIndication())
Himani Chawla26e555c2020-08-31 12:30:20 +0530336 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000337 // no change, nothing really to do - return success
Himani Chawla26e555c2020-08-31 12:30:20 +0530338 return nil
339}
340
Himani Chawla6d2ae152020-09-02 13:11:20 +0530341func (dh *deviceHandler) processInterAdapterDeleteGemPortReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530342 msg *ic.InterAdapterMessage) error {
343
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000344 pDevEntry := dh.getOnuDeviceEntry(true)
345 if pDevEntry == nil {
346 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
347 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
348 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530349 if dh.pOnuTP == nil {
350 //should normally not happen ...
351 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
352 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000353 return fmt.Errorf("techProfile DelGem request while onuTechProf instance not setup: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530354 }
355
356 msgBody := msg.GetBody()
357 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
358 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
359 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
360 "device-id": dh.deviceID, "error": err})
361 return err
362 }
363
364 //compare TECH_PROFILE_DOWNLOAD_REQUEST
365 dh.pOnuTP.lockTpProcMutex()
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000366 defer dh.pOnuTP.unlockTpProcMutex()
367 pDevEntry.lockOnuKVStoreMutex()
368 defer pDevEntry.unlockOnuKVStoreMutex()
Himani Chawla26e555c2020-08-31 12:30:20 +0530369
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000370 if delGemPortMsg.UniId > 255 {
371 return fmt.Errorf(fmt.Sprintf("received UniId value exceeds range: %d, device-id: %s",
372 delGemPortMsg.UniId, dh.deviceID))
373 }
374 uniID := uint8(delGemPortMsg.UniId)
Himani Chawla26e555c2020-08-31 12:30:20 +0530375
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000376 if bTpModify := pDevEntry.updateOnuUniTpPath(uniID, ""); bTpModify {
377 // deadline context to ensure completion of background routines waited for
Himani Chawlad96df182020-09-28 11:12:02 +0530378 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000379 dctx, cancel := context.WithDeadline(context.Background(), deadline)
380
381 dh.pOnuTP.resetTpProcessingErrorIndication()
382 pDevEntry.resetKvProcessingErrorIndication()
383
384 var wg sync.WaitGroup
385 wg.Add(2) // for the 2 go routines to finish
386 go pDevEntry.deleteTpResource(dctx, uniID, delGemPortMsg.TpPath,
387 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
388 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
389 go pDevEntry.updateOnuKvStore(dctx, &wg)
mpagenko01e726e2020-10-23 09:45:29 +0000390 dh.waitForCompletion(cancel, &wg, "GemDelete") //wait for background process to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000391
392 return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(), pDevEntry.getKvProcessingErrorIndication())
393 }
394 return nil
Himani Chawla26e555c2020-08-31 12:30:20 +0530395}
396
Himani Chawla6d2ae152020-09-02 13:11:20 +0530397func (dh *deviceHandler) processInterAdapterDeleteTcontReqMessage(
Himani Chawla26e555c2020-08-31 12:30:20 +0530398 msg *ic.InterAdapterMessage) error {
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000399
400 pDevEntry := dh.getOnuDeviceEntry(true)
401 if pDevEntry == nil {
402 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
403 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
404 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530405 if dh.pOnuTP == nil {
406 //should normally not happen ...
407 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
408 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000409 return fmt.Errorf("techProfile DelTcont request while onuTechProf instance not setup: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530410 }
411
412 msgBody := msg.GetBody()
413 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
414 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
415 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
416 "device-id": dh.deviceID, "error": err})
417 return err
418 }
419
420 //compare TECH_PROFILE_DOWNLOAD_REQUEST
421 dh.pOnuTP.lockTpProcMutex()
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000422 defer dh.pOnuTP.unlockTpProcMutex()
423 pDevEntry.lockOnuKVStoreMutex()
424 defer pDevEntry.unlockOnuKVStoreMutex()
425
426 if delTcontMsg.UniId > 255 {
427 return fmt.Errorf(fmt.Sprintf("received UniId value exceeds range: %d, device-id: %s",
428 delTcontMsg.UniId, dh.deviceID))
429 }
430 uniID := uint8(delTcontMsg.UniId)
431
432 if bTpModify := pDevEntry.updateOnuUniTpPath(uniID, ""); bTpModify {
Himani Chawla26e555c2020-08-31 12:30:20 +0530433 // deadline context to ensure completion of background routines waited for
Himani Chawlad96df182020-09-28 11:12:02 +0530434 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Himani Chawla26e555c2020-08-31 12:30:20 +0530435 dctx, cancel := context.WithDeadline(context.Background(), deadline)
436
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000437 dh.pOnuTP.resetTpProcessingErrorIndication()
438 pDevEntry.resetKvProcessingErrorIndication()
439
Himani Chawla26e555c2020-08-31 12:30:20 +0530440 var wg sync.WaitGroup
441 wg.Add(2) // for the 2 go routines to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000442 go pDevEntry.deleteTpResource(dctx, uniID, delTcontMsg.TpPath,
Himani Chawla26e555c2020-08-31 12:30:20 +0530443 cResourceTcont, delTcontMsg.AllocId, &wg)
444 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000445 go pDevEntry.updateOnuKvStore(dctx, &wg)
mpagenko01e726e2020-10-23 09:45:29 +0000446 dh.waitForCompletion(cancel, &wg, "TContDelete") //wait for background process to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000447
448 return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(), pDevEntry.getKvProcessingErrorIndication())
Himani Chawla26e555c2020-08-31 12:30:20 +0530449 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530450 return nil
451}
452
Himani Chawla6d2ae152020-09-02 13:11:20 +0530453//processInterAdapterMessage sends the proxied messages to the target device
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000454// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
455// is meant, and then send the unmarshalled omci message to this onu
Himani Chawla6d2ae152020-09-02 13:11:20 +0530456func (dh *deviceHandler) processInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000457 msgID := msg.Header.Id
458 msgType := msg.Header.Type
459 fromTopic := msg.Header.FromTopic
460 toTopic := msg.Header.ToTopic
461 toDeviceID := msg.Header.ToDeviceId
462 proxyDeviceID := msg.Header.ProxyDeviceId
463 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
464 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
465
466 switch msgType {
467 case ic.InterAdapterMessageType_OMCI_REQUEST:
468 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530469 return dh.processInterAdapterOMCIReqMessage(msg)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000470 }
471 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
472 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530473 return dh.processInterAdapterONUIndReqMessage(msg)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000474 }
mpagenkoaf801632020-07-03 10:00:42 +0000475 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
476 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530477 return dh.processInterAdapterTechProfileDownloadReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000478 }
479 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
480 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530481 return dh.processInterAdapterDeleteGemPortReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000482
mpagenkoaf801632020-07-03 10:00:42 +0000483 }
484 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
485 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530486 return dh.processInterAdapterDeleteTcontReqMessage(msg)
mpagenkoaf801632020-07-03 10:00:42 +0000487 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000488 default:
489 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000490 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000491 "msgType": msg.Header.Type, "device-id": dh.deviceID})
492 return fmt.Errorf("inter-adapter-unhandled-type: %d, %s", msg.Header.Type, dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000493 }
494 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000495}
496
mpagenkodff5dda2020-08-28 11:52:01 +0000497//FlowUpdateIncremental removes and/or adds the flow changes on a given device
Himani Chawla6d2ae152020-09-02 13:11:20 +0530498func (dh *deviceHandler) FlowUpdateIncremental(apOfFlowChanges *openflow_13.FlowChanges,
mpagenkodff5dda2020-08-28 11:52:01 +0000499 apOfGroupChanges *openflow_13.FlowGroupChanges, apFlowMetaData *voltha.FlowMetadata) error {
mpagenko01e726e2020-10-23 09:45:29 +0000500 logger.Debugw("FlowUpdateIncremental started", log.Fields{"device-id": dh.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000501
mpagenko01e726e2020-10-23 09:45:29 +0000502 var retError error = nil
503 //Remove flows (always remove flows first - remove old and add new with same cookie may be part of the same request)
mpagenkodff5dda2020-08-28 11:52:01 +0000504 if apOfFlowChanges.ToRemove != nil {
505 for _, flowItem := range apOfFlowChanges.ToRemove.Items {
mpagenkodff5dda2020-08-28 11:52:01 +0000506 if flowItem.GetCookie() == 0 {
mpagenko01e726e2020-10-23 09:45:29 +0000507 logger.Warnw("flow-remove no cookie: ignore and continuing on checking further flows", log.Fields{
508 "device-id": dh.deviceID})
509 retError = fmt.Errorf("flow-remove no cookie, device-id %s", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +0000510 continue
511 }
512 flowInPort := flow.GetInPort(flowItem)
513 if flowInPort == uint32(of.OfpPortNo_OFPP_INVALID) {
mpagenko01e726e2020-10-23 09:45:29 +0000514 logger.Warnw("flow-remove inPort invalid: ignore and continuing on checking further flows", log.Fields{"device-id": dh.deviceID})
515 retError = fmt.Errorf("flow-remove inPort invalid, device-id %s", dh.deviceID)
516 continue
517 //return fmt.Errorf("flow inPort invalid: %s", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +0000518 } else if flowInPort == dh.ponPortNumber {
mpagenko01e726e2020-10-23 09:45:29 +0000519 //this is some downstream flow, not regarded as error, just ignored
520 logger.Debugw("flow-remove for downstream: ignore and continuing on checking further flows", log.Fields{
521 "device-id": dh.deviceID, "inPort": flowInPort})
mpagenkodff5dda2020-08-28 11:52:01 +0000522 continue
523 } else {
524 // this is the relevant upstream flow
Himani Chawla6d2ae152020-09-02 13:11:20 +0530525 var loUniPort *onuUniPort
mpagenkodff5dda2020-08-28 11:52:01 +0000526 if uniPort, exist := dh.uniEntityMap[flowInPort]; exist {
527 loUniPort = uniPort
528 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000529 logger.Warnw("flow-remove inPort not found in UniPorts: ignore and continuing on checking further flows",
530 log.Fields{"device-id": dh.deviceID, "inPort": flowInPort})
531 retError = fmt.Errorf("flow-remove inPort not found in UniPorts, inPort %d, device-id %s",
532 flowInPort, dh.deviceID)
533 continue
534 //return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
mpagenkodff5dda2020-08-28 11:52:01 +0000535 }
536 flowOutPort := flow.GetOutPort(flowItem)
mpagenko01e726e2020-10-23 09:45:29 +0000537 logger.Debugw("flow-remove port indications", log.Fields{
538 "device-id": dh.deviceID, "inPort": flowInPort, "outPort": flowOutPort,
mpagenkodff5dda2020-08-28 11:52:01 +0000539 "uniPortName": loUniPort.name})
mpagenko01e726e2020-10-23 09:45:29 +0000540 err := dh.removeFlowItemFromUniPort(flowItem, loUniPort)
541 //try next flow after processing error
mpagenkodff5dda2020-08-28 11:52:01 +0000542 if err != nil {
mpagenko01e726e2020-10-23 09:45:29 +0000543 logger.Warnw("flow-remove processing error: continuing on checking further flows",
544 log.Fields{"device-id": dh.deviceID, "error": err})
545 retError = err
546 continue
547 //return err
548 } else { // if last setting succeeds, overwrite possibly previously set error
549 retError = nil
mpagenkodff5dda2020-08-28 11:52:01 +0000550 }
551 }
552 }
553 }
mpagenko01e726e2020-10-23 09:45:29 +0000554 if apOfFlowChanges.ToAdd != nil {
555 for _, flowItem := range apOfFlowChanges.ToAdd.Items {
556 if flowItem.GetCookie() == 0 {
557 logger.Debugw("incremental flow-add no cookie: ignore and continuing on checking further flows", log.Fields{
558 "device-id": dh.deviceID})
559 retError = fmt.Errorf("flow-add no cookie, device-id %s", dh.deviceID)
560 continue
561 }
562 flowInPort := flow.GetInPort(flowItem)
563 if flowInPort == uint32(of.OfpPortNo_OFPP_INVALID) {
564 logger.Warnw("flow-add inPort invalid: ignore and continuing on checking further flows", log.Fields{"device-id": dh.deviceID})
565 retError = fmt.Errorf("flow-add inPort invalid, device-id %s", dh.deviceID)
566 continue
567 //return fmt.Errorf("flow inPort invalid: %s", dh.deviceID)
568 } else if flowInPort == dh.ponPortNumber {
569 //this is some downstream flow
570 logger.Debugw("flow-add for downstream: ignore and continuing on checking further flows", log.Fields{
571 "device-id": dh.deviceID, "inPort": flowInPort})
572 continue
573 } else {
574 // this is the relevant upstream flow
575 var loUniPort *onuUniPort
576 if uniPort, exist := dh.uniEntityMap[flowInPort]; exist {
577 loUniPort = uniPort
578 } else {
579 logger.Warnw("flow-add inPort not found in UniPorts: ignore and continuing on checking further flows",
580 log.Fields{"device-id": dh.deviceID, "inPort": flowInPort})
581 retError = fmt.Errorf("flow-add inPort not found in UniPorts, inPort %d, device-id %s",
582 flowInPort, dh.deviceID)
583 continue
584 //return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
585 }
586 flowOutPort := flow.GetOutPort(flowItem)
587 logger.Debugw("flow-add port indications", log.Fields{
588 "device-id": dh.deviceID, "inPort": flowInPort, "outPort": flowOutPort,
589 "uniPortName": loUniPort.name})
590 err := dh.addFlowItemToUniPort(flowItem, loUniPort)
591 //try next flow after processing error
592 if err != nil {
593 logger.Warnw("flow-add processing error: continuing on checking further flows",
594 log.Fields{"device-id": dh.deviceID, "error": err})
595 retError = err
596 continue
597 //return err
598 } else { // if last setting succeeds, overwrite possibly previously set error
599 retError = nil
600 }
601 }
602 }
603 }
604 return retError
mpagenkodff5dda2020-08-28 11:52:01 +0000605}
606
Himani Chawla6d2ae152020-09-02 13:11:20 +0530607//disableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530608func (dh *deviceHandler) disableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000609 logger.Debugw("disable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000610
mpagenko900ee4b2020-10-12 11:56:34 +0000611 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly
612 // - inblock state checking to prevent possibly unneeded processing (on command repitition)
mpagenko3af1f032020-06-10 08:53:41 +0000613 if dh.deviceReason != "omci-admin-lock" {
mpagenko900ee4b2020-10-12 11:56:34 +0000614 //running FSM's are stopped/reset here to avoid indirect stucking
615 // due to blocked OMCI transmission on disabled state
616 // but with possibly aborted FSM's there might be complications as the expected state
617 // after some re-enable would then be quite undefined
618 // maybe after re-enabling some additional checks would be required to possibly enforce new
619 // (reconcile-like) config (which would require some indication from 'aborted' FSM's first)
620 // for now let's assume no running FSM is active at this time point here ... -> TODO!!!
621 if err := dh.resetFsms(); err != nil {
622 logger.Errorw("error-disableDevice at FSM stop",
623 log.Fields{"device-id": dh.deviceID, "error": err})
624 // abort: system behavior is just unstable ...
625 return
626 }
627
mpagenko01e726e2020-10-23 09:45:29 +0000628 if dh.deviceReason != "rebooting" {
629 // disable UNI ports/ONU
630 // *** should generate UniDisableStateDone event - used to disable the port(s) on success
631 if dh.pLockStateFsm == nil {
632 dh.createUniLockFsm(true, UniDisableStateDone)
633 } else { //LockStateFSM already init
634 dh.pLockStateFsm.setSuccessEvent(UniDisableStateDone)
635 dh.runUniLockFsm(true)
636 }
637 } else {
638 logger.Debugw("DeviceStateUpdate upon disable", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
639 "OperStatus": voltha.OperStatus_UNKNOWN, "device-id": dh.deviceID})
640 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(),
641 dh.deviceID, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
642 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
643 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
644 }
645
646 logger.Debugw("DeviceReasonUpdate upon re-enable", log.Fields{
647 "reason": "omci-admin-lock", "device-id": dh.deviceID})
648 // DeviceReason to update acc.to modified py code as per beginning of Sept 2020
649 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
650 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
651 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
652 }
653 dh.deviceReason = "omci-admin-lock"
654
655 //stop the device entry which resets the attached omciCC
656 pDevEntry := dh.getOnuDeviceEntry(false)
657 if pDevEntry == nil {
658 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
659 return
660 }
661 _ = pDevEntry.stop(context.TODO(), true) //stop deviceEntry with omciCC reset
mpagenko3af1f032020-06-10 08:53:41 +0000662 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300663 }
664}
665
Himani Chawla6d2ae152020-09-02 13:11:20 +0530666//reEnableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530667func (dh *deviceHandler) reEnableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000668 logger.Debugw("reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000669
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000670 // enable ONU/UNI ports
mpagenko900ee4b2020-10-12 11:56:34 +0000671 // *** should generate UniEnableStateDone event - used to disable the port(s) on success
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000672 if dh.pUnlockStateFsm == nil {
mpagenko900ee4b2020-10-12 11:56:34 +0000673 dh.createUniLockFsm(false, UniEnableStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000674 } else { //UnlockStateFSM already init
mpagenko900ee4b2020-10-12 11:56:34 +0000675 dh.pUnlockStateFsm.setSuccessEvent(UniEnableStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000676 dh.runUniLockFsm(false)
677 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300678}
679
Himani Chawla6d2ae152020-09-02 13:11:20 +0530680func (dh *deviceHandler) reconcileDeviceOnuInd() {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000681 logger.Debugw("reconciling - simulate onu indication", log.Fields{"device-id": dh.deviceID})
682
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000683 pDevEntry := dh.getOnuDeviceEntry(true)
684 if pDevEntry == nil {
685 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
686 return
687 }
688 if err := pDevEntry.restoreDataFromOnuKvStore(context.TODO()); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000689 logger.Errorw("reconciling - restoring OnuTp-data failed - abort", log.Fields{"err": err, "device-id": dh.deviceID})
690 dh.reconciling = false
691 return
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000692 }
Himani Chawla4d908332020-08-31 12:30:20 +0530693 var onuIndication oop.OnuIndication
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000694 onuIndication.IntfId = pDevEntry.sOnuPersistentData.PersIntfID
695 onuIndication.OnuId = pDevEntry.sOnuPersistentData.PersOnuID
696 onuIndication.OperState = pDevEntry.sOnuPersistentData.PersOperState
697 onuIndication.AdminState = pDevEntry.sOnuPersistentData.PersAdminState
Himani Chawla4d908332020-08-31 12:30:20 +0530698 _ = dh.createInterface(&onuIndication)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000699}
700
Himani Chawla6d2ae152020-09-02 13:11:20 +0530701func (dh *deviceHandler) reconcileDeviceTechProf() {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000702 logger.Debugw("reconciling - trigger tech profile config", log.Fields{"device-id": dh.deviceID})
703
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000704 pDevEntry := dh.getOnuDeviceEntry(true)
705 if pDevEntry == nil {
706 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
707 return
708 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000709
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000710 dh.pOnuTP.lockTpProcMutex()
711 defer dh.pOnuTP.unlockTpProcMutex()
712
713 for _, uniData := range pDevEntry.sOnuPersistentData.PersUniConfig {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000714 // deadline context to ensure completion of background routines waited for
715 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +0530716 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000717 dctx, cancel := context.WithDeadline(context.Background(), deadline)
718
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000719 dh.pOnuTP.resetTpProcessingErrorIndication()
720
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000721 var wg sync.WaitGroup
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000722 wg.Add(1) // for the 1 go routine to finish
723 go dh.pOnuTP.configureUniTp(dctx, uniData.PersUniID, uniData.PersTpPath, &wg)
mpagenko01e726e2020-10-23 09:45:29 +0000724 dh.waitForCompletion(cancel, &wg, "TechProfReconcile") //wait for background process to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000725
726 if err := dh.pOnuTP.getTpProcessingErrorIndication(); err != nil {
727 logger.Errorw(err.Error(), log.Fields{"device-id": dh.deviceID})
728 }
729 }
730}
731
732func (dh *deviceHandler) reconcileDeviceFlowConfig() {
733 logger.Debugw("reconciling - trigger flow config", log.Fields{"device-id": dh.deviceID})
734
735 pDevEntry := dh.getOnuDeviceEntry(true)
736 if pDevEntry == nil {
737 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000738 return
739 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000740 for _, uniData := range pDevEntry.sOnuPersistentData.PersUniConfig {
741 var uniPort *onuUniPort
742 var exist bool
743 uniNo := mkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(), uint32(uniData.PersUniID))
744 if uniPort, exist = dh.uniEntityMap[uniNo]; !exist {
mpagenko01e726e2020-10-23 09:45:29 +0000745 logger.Errorw("onuUniPort data not found!", log.Fields{"uniNo": uniNo, "device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000746 return
747 }
748 for _, flowData := range uniData.PersFlowParams {
mpagenko01e726e2020-10-23 09:45:29 +0000749 logger.Debugw("add flow with cookie slice", log.Fields{"device-id": dh.deviceID, "cookies": flowData.CookieSlice})
750 //the slice can be passed 'by value' here, - which internally passes its reference copy
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000751 if _, exist = dh.UniVlanConfigFsmMap[uniData.PersUniID]; exist {
mpagenko01e726e2020-10-23 09:45:29 +0000752 if err := dh.UniVlanConfigFsmMap[uniData.PersUniID].SetUniFlowParams(flowData.VlanRuleParams.TpID,
753 flowData.CookieSlice, uint16(flowData.VlanRuleParams.MatchVid), uint16(flowData.VlanRuleParams.SetVid),
754 uint8(flowData.VlanRuleParams.SetPcp)); err != nil {
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000755 logger.Errorw(err.Error(), log.Fields{"device-id": dh.deviceID})
756 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000757 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000758 if err := dh.createVlanFilterFsm(uniPort, flowData.VlanRuleParams.TpID, flowData.CookieSlice,
759 uint16(flowData.VlanRuleParams.MatchVid), uint16(flowData.VlanRuleParams.SetVid),
760 uint8(flowData.VlanRuleParams.SetPcp), OmciVlanFilterDone); err != nil {
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000761 logger.Errorw(err.Error(), log.Fields{"device-id": dh.deviceID})
762 }
763 }
764 }
765 }
766}
767
768func (dh *deviceHandler) reconcileMetrics() {
769 logger.Debugw("reconciling - trigger metrics - to be implemented in scope of VOL-3324!", log.Fields{"device-id": dh.deviceID})
770
771 //TODO: reset of reconciling-flag has always to be done in the last reconcile*() function
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000772 dh.reconciling = false
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000773}
774
Himani Chawla6d2ae152020-09-02 13:11:20 +0530775func (dh *deviceHandler) deleteDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000776 logger.Debugw("delete-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000777
778 pDevEntry := dh.getOnuDeviceEntry(true)
779 if pDevEntry == nil {
780 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
781 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000782 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000783 pDevEntry.lockOnuKVStoreMutex()
784 defer pDevEntry.unlockOnuKVStoreMutex()
785
786 // deadline context to ensure completion of background routines waited for
787 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +0530788 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000789 dctx, cancel := context.WithDeadline(context.Background(), deadline)
790
791 pDevEntry.resetKvProcessingErrorIndication()
792
793 var wg sync.WaitGroup
794 wg.Add(1) // for the 1 go routine to finish
795 go pDevEntry.deleteDataFromOnuKvStore(dctx, &wg)
mpagenko01e726e2020-10-23 09:45:29 +0000796 dh.waitForCompletion(cancel, &wg, "DeleteDevice") //wait for background process to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000797
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000798 // TODO: further actions - stop metrics and FSMs, remove device ...
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000799 return pDevEntry.getKvProcessingErrorIndication()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000800}
801
Himani Chawla6d2ae152020-09-02 13:11:20 +0530802func (dh *deviceHandler) rebootDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000803 logger.Debugw("reboot-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300804 if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
divyadesai4d299552020-08-18 07:13:49 +0000805 logger.Errorw("device-unreachable", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000806 return fmt.Errorf("device-unreachable: %s, %s", dh.deviceID, device.SerialNumber)
ozgecanetsiae11479f2020-07-06 09:44:47 +0300807 }
Himani Chawla6d2ae152020-09-02 13:11:20 +0530808 if err := dh.pOnuOmciDevice.reboot(context.TODO()); err != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530809 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
810 logger.Errorw("error-rebooting-device", log.Fields{"device-id": dh.deviceID, "error": err})
811 return err
812 }
mpagenko01e726e2020-10-23 09:45:29 +0000813
814 //transfer the possibly modified logical uni port state
815 dh.disableUniPortStateUpdate()
816
Andrea Campanellabef4e542020-10-22 11:01:28 +0200817 logger.Debugw("call DeviceStateUpdate upon reboot", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
Holger Hildebrandt8165eda2020-09-24 09:39:24 +0000818 "OperStatus": voltha.OperStatus_DISCOVERED, "device-id": dh.deviceID})
Andrea Campanellabef4e542020-10-22 11:01:28 +0200819 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
ozgecanetsiae11479f2020-07-06 09:44:47 +0300820 voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000821 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000822 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300823 return err
824 }
Andrea Campanellabef4e542020-10-22 11:01:28 +0200825 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000826 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000827 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300828 return err
829 }
mpagenko01e726e2020-10-23 09:45:29 +0000830 dh.deviceReason = "rebooting"
ozgecanetsiae11479f2020-07-06 09:44:47 +0300831 return nil
832}
833
Himani Chawla6d2ae152020-09-02 13:11:20 +0530834// deviceHandler methods that implement the adapters interface requests## end #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000835// #####################################################################################
836
837// ################ to be updated acc. needs of ONU Device ########################
Himani Chawla6d2ae152020-09-02 13:11:20 +0530838// deviceHandler StateMachine related state transition methods ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000839
Himani Chawla6d2ae152020-09-02 13:11:20 +0530840func (dh *deviceHandler) logStateChange(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000841 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})
842}
843
844// doStateInit provides the device update to the core
Himani Chawla6d2ae152020-09-02 13:11:20 +0530845func (dh *deviceHandler) doStateInit(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000846
847 logger.Debug("doStateInit-started")
848 var err error
849
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000850 // populate what we know. rest comes later after mib sync
851 dh.device.Root = false
852 dh.device.Vendor = "OpenONU"
853 dh.device.Model = "go"
854 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000855 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000856
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000857 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000858
859 if !dh.reconciling {
Himani Chawla4d908332020-08-31 12:30:20 +0530860 _ = dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000861 } else {
862 logger.Debugw("reconciling - don't notify core about DeviceUpdate",
863 log.Fields{"device-id": dh.deviceID})
864 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000865
Himani Chawla4d908332020-08-31 12:30:20 +0530866 dh.parentID = dh.device.ParentId
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000867 dh.ponPortNumber = dh.device.ParentPortNo
868
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000869 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
870 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
871 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
divyadesai4d299552020-08-18 07:13:49 +0000872 logger.Debugw("device-updated", log.Fields{"device-id": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000873 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Himani Chawla4d908332020-08-31 12:30:20 +0530874 "ParentId": dh.parentID, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000875
876 /*
877 self._pon = PonPort.create(self, self._pon_port_number)
878 self._pon.add_peer(self.parent_id, self._pon_port_number)
879 self.logger.debug('adding-pon-port-to-agent',
880 type=self._pon.get_port().type,
881 admin_state=self._pon.get_port().admin_state,
882 oper_status=self._pon.get_port().oper_status,
883 )
884 */
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000885 if !dh.reconciling {
mpagenko01e726e2020-10-23 09:45:29 +0000886 logger.Debugw("adding-pon-port", log.Fields{"device-id": dh.deviceID, "ponPortNo": dh.ponPortNumber})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000887 var ponPortNo uint32 = 1
888 if dh.ponPortNumber != 0 {
889 ponPortNo = dh.ponPortNumber
890 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000891
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000892 pPonPort := &voltha.Port{
893 PortNo: ponPortNo,
894 Label: fmt.Sprintf("pon-%d", ponPortNo),
895 Type: voltha.Port_PON_ONU,
896 OperStatus: voltha.OperStatus_ACTIVE,
Himani Chawla4d908332020-08-31 12:30:20 +0530897 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentID, // Peer device is OLT
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000898 PortNo: ponPortNo}}, // Peer port is parent's port number
899 }
900 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
901 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
902 e.Cancel(err)
903 return
904 }
905 } else {
906 logger.Debugw("reconciling - pon-port already added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000907 }
908 logger.Debug("doStateInit-done")
909}
910
911// postInit setups the DeviceEntry for the conerned device
Himani Chawla6d2ae152020-09-02 13:11:20 +0530912func (dh *deviceHandler) postInit(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000913
914 logger.Debug("postInit-started")
915 var err error
916 /*
917 dh.Client = oop.NewOpenoltClient(dh.clientCon)
918 dh.pTransitionMap.Handle(ctx, GrpcConnected)
919 return nil
920 */
Himani Chawla6d2ae152020-09-02 13:11:20 +0530921 if err = dh.addOnuDeviceEntry(context.TODO()); err != nil {
922 logger.Fatalf("Device FSM: addOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000923 e.Cancel(err)
924 return
925 }
926
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000927 if dh.reconciling {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530928 go dh.reconcileDeviceOnuInd()
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000929 // reconcilement will be continued after mib download is done
930 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000931 /*
932 ############################################################################
933 # Setup Alarm handler
934 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
935 device.serial_number)
936 ############################################################################
937 # Setup PM configuration for this device
938 # Pass in ONU specific options
939 kwargs = {
940 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
941 'heartbeat': self.heartbeat,
942 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
943 }
944 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
945 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
946 self.logical_device_id, device.serial_number,
947 grouped=True, freq_override=False, **kwargs)
948 pm_config = self._pm_metrics.make_proto()
949 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
950 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
951 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
952
953 # Note, ONU ID and UNI intf set in add_uni_port method
954 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
955 ani_ports=[self._pon])
956
957 # Code to Run OMCI Test Action
958 kwargs_omci_test_action = {
959 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
960 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
961 }
962 serial_number = device.serial_number
963 self._test_request = OmciTestRequest(self.core_proxy,
964 self.omci_agent, self.device_id,
965 AniG, serial_number,
966 self.logical_device_id,
967 exclusive=False,
968 **kwargs_omci_test_action)
969
970 self.enabled = True
971 else:
972 self.logger.info('onu-already-activated')
973 */
974 logger.Debug("postInit-done")
975}
976
977// doStateConnected get the device info and update to voltha core
978// for comparison of the original method (not that easy to uncomment): compare here:
979// voltha-openolt-adapter/adaptercore/device_handler.go
980// -> this one obviously initiates all communication interfaces of the device ...?
Himani Chawla6d2ae152020-09-02 13:11:20 +0530981func (dh *deviceHandler) doStateConnected(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000982
983 logger.Debug("doStateConnected-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530984 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000985 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000986 logger.Debug("doStateConnected-done")
987}
988
989// doStateUp handle the onu up indication and update to voltha core
Himani Chawla6d2ae152020-09-02 13:11:20 +0530990func (dh *deviceHandler) doStateUp(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000991
992 logger.Debug("doStateUp-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530993 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000994 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000995 logger.Debug("doStateUp-done")
996
997 /*
998 // Synchronous call to update device state - this method is run in its own go routine
999 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
1000 voltha.OperStatus_ACTIVE); err != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001001 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"device-id": dh.device.Id, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001002 return err
1003 }
1004 return nil
1005 */
1006}
1007
1008// doStateDown handle the onu down indication
Himani Chawla6d2ae152020-09-02 13:11:20 +05301009func (dh *deviceHandler) doStateDown(e *fsm.Event) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001010
1011 logger.Debug("doStateDown-started")
1012 var err error
1013
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001014 device := dh.device
1015 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001016 /*TODO: needs to handle error scenarios */
Andrea Campanella6515c582020-10-05 11:25:00 +02001017 logger.Errorw("Failed to fetch handler device", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001018 e.Cancel(err)
1019 return
1020 }
1021
1022 cloned := proto.Clone(device).(*voltha.Device)
1023 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
1024 /*
1025 // Update the all ports state on that device to disable
1026 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001027 logger.Errorw("updating-ports-failed", log.Fields{"device-id": device.Id, "error": er})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001028 return er
1029 }
1030
1031 //Update the device oper state and connection status
1032 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1033 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
1034 dh.device = cloned
1035
1036 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001037 logger.Errorw("error-updating-device-state", log.Fields{"device-id": device.Id, "error": er})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001038 return er
1039 }
1040
1041 //get the child device for the parent device
1042 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
1043 if err != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001044 logger.Errorw("failed to get child devices information", log.Fields{"device-id": dh.device.Id, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001045 return err
1046 }
1047 for _, onuDevice := range onuDevices.Items {
1048
1049 // Update onu state as down in onu adapter
1050 onuInd := oop.OnuIndication{}
1051 onuInd.OperState = "down"
1052 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1053 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1054 if er != nil {
1055 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
mpagenko01e726e2020-10-23 09:45:29 +00001056 "From Adapter": "openolt", "DevieType": onuDevice.Type, "device-id": onuDevice.Id})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001057 //Do not return here and continue to process other ONUs
1058 }
1059 }
1060 // * Discovered ONUs entries need to be cleared , since after OLT
1061 // is up, it starts sending discovery indications again* /
1062 dh.discOnus = sync.Map{}
mpagenko01e726e2020-10-23 09:45:29 +00001063 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001064 return nil
1065 */
Himani Chawla4d908332020-08-31 12:30:20 +05301066 err = errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001067 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001068 logger.Debug("doStateDown-done")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001069}
1070
Himani Chawla6d2ae152020-09-02 13:11:20 +05301071// deviceHandler StateMachine related state transition methods ##### end #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001072// #################################################################################
1073
1074// ###################################################
Himani Chawla6d2ae152020-09-02 13:11:20 +05301075// deviceHandler utility methods ##### begin #########
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001076
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001077//getOnuDeviceEntry gets the ONU device entry and may wait until its value is defined
Himani Chawla6d2ae152020-09-02 13:11:20 +05301078func (dh *deviceHandler) getOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
mpagenko3af1f032020-06-10 08:53:41 +00001079 dh.lockDevice.RLock()
1080 pOnuDeviceEntry := dh.pOnuOmciDevice
1081 if aWait && pOnuDeviceEntry == nil {
1082 //keep the read sema short to allow for subsequent write
1083 dh.lockDevice.RUnlock()
divyadesai4d299552020-08-18 07:13:49 +00001084 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001085 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
1086 // so it might be needed to wait here for that event with some timeout
1087 select {
1088 case <-time.After(60 * time.Second): //timer may be discussed ...
divyadesai4d299552020-08-18 07:13:49 +00001089 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001090 return nil
1091 case <-dh.deviceEntrySet:
divyadesai4d299552020-08-18 07:13:49 +00001092 logger.Debugw("devicEntry ready now - continue", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001093 // if written now, we can return the written value without sema
1094 return dh.pOnuOmciDevice
1095 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001096 }
mpagenko3af1f032020-06-10 08:53:41 +00001097 dh.lockDevice.RUnlock()
1098 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001099}
1100
Himani Chawla6d2ae152020-09-02 13:11:20 +05301101//setOnuDeviceEntry sets the ONU device entry within the handler
1102func (dh *deviceHandler) setOnuDeviceEntry(
1103 apDeviceEntry *OnuDeviceEntry, apOnuTp *onuUniTechProf) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001104 dh.lockDevice.Lock()
1105 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +00001106 dh.pOnuOmciDevice = apDeviceEntry
1107 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001108}
1109
Himani Chawla6d2ae152020-09-02 13:11:20 +05301110//addOnuDeviceEntry creates a new ONU device or returns the existing
1111func (dh *deviceHandler) addOnuDeviceEntry(ctx context.Context) error {
divyadesai4d299552020-08-18 07:13:49 +00001112 logger.Debugw("adding-deviceEntry", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001113
Himani Chawla6d2ae152020-09-02 13:11:20 +05301114 deviceEntry := dh.getOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001115 if deviceEntry == nil {
1116 /* costum_me_map in python code seems always to be None,
1117 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
1118 /* also no 'clock' argument - usage open ...*/
1119 /* and no alarm_db yet (oo.alarm_db) */
Himani Chawla6d2ae152020-09-02 13:11:20 +05301120 deviceEntry = newOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
mpagenkoaf801632020-07-03 10:00:42 +00001121 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001122 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001123 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenko01e726e2020-10-23 09:45:29 +00001124 onuTechProfProc := newOnuUniTechProf(ctx, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001125 //error treatment possible //TODO!!!
Himani Chawla6d2ae152020-09-02 13:11:20 +05301126 dh.setOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +00001127 // fire deviceEntry ready event to spread to possibly waiting processing
1128 dh.deviceEntrySet <- true
divyadesai4d299552020-08-18 07:13:49 +00001129 logger.Infow("onuDeviceEntry-added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001130 } else {
divyadesai4d299552020-08-18 07:13:49 +00001131 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001132 }
1133 // might be updated with some error handling !!!
1134 return nil
1135}
1136
1137// doStateInit provides the device update to the core
Himani Chawla6d2ae152020-09-02 13:11:20 +05301138func (dh *deviceHandler) createInterface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001139 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
1140 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
1141
1142 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001143
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001144 if !dh.reconciling {
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001145 logger.Debugw("call DeviceStateUpdate upon create interface", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
1146 "OperStatus": voltha.OperStatus_ACTIVATING, "device-id": dh.deviceID})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001147 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1148 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
1149 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1150 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1151 }
1152 } else {
1153 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVATING",
1154 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001155 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001156 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
1157 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
1158 // 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 +00001159 // 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 +00001160 // so let's just try to keep it simple ...
1161 /*
1162 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
1163 if err != nil || device == nil {
1164 //TODO: needs to handle error scenarios
1165 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
1166 return errors.New("Voltha Device not found")
1167 }
1168 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001169
Himani Chawla6d2ae152020-09-02 13:11:20 +05301170 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenko3af1f032020-06-10 08:53:41 +00001171 if pDevEntry != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +05301172 if err := pDevEntry.start(context.TODO()); err != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301173 return err
1174 }
mpagenko3af1f032020-06-10 08:53:41 +00001175 } else {
divyadesai4d299552020-08-18 07:13:49 +00001176 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001177 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
mpagenko3af1f032020-06-10 08:53:41 +00001178 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001179 if !dh.reconciling {
1180 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
1181 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1182 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"device-id": dh.deviceID, "error": err})
1183 }
1184 } else {
1185 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to starting-openomci",
1186 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001187 }
mpagenko3af1f032020-06-10 08:53:41 +00001188 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001189
1190 /* this might be a good time for Omci Verify message? */
1191 verifyExec := make(chan bool)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301192 omciVerify := newOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +00001193 dh.device.Id, pDevEntry.PDevOmciCC,
mpagenko900ee4b2020-10-12 11:56:34 +00001194 true, true) //exclusive and allowFailure (anyway not yet checked)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301195 omciVerify.performOmciTest(context.TODO(), verifyExec)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001196
1197 /* give the handler some time here to wait for the OMCi verification result
1198 after Timeout start and try MibUpload FSM anyway
1199 (to prevent stopping on just not supported OMCI verification from ONU) */
1200 select {
1201 case <-time.After(2 * time.Second):
1202 logger.Warn("omci start-verification timed out (continue normal)")
1203 case testresult := <-verifyExec:
1204 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
1205 }
1206
1207 /* In py code it looks earlier (on activate ..)
1208 # Code to Run OMCI Test Action
1209 kwargs_omci_test_action = {
1210 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
1211 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
1212 }
1213 serial_number = device.serial_number
1214 self._test_request = OmciTestRequest(self.core_proxy,
1215 self.omci_agent, self.device_id,
1216 AniG, serial_number,
1217 self.logical_device_id,
1218 exclusive=False,
1219 **kwargs_omci_test_action)
1220 ...
1221 # Start test requests after a brief pause
1222 if not self._test_request_started:
1223 self._test_request_started = True
1224 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
1225 reactor.callLater(tststart, self._test_request.start_collector)
1226
1227 */
1228 /* which is then: in omci_test_request.py : */
1229 /*
1230 def start_collector(self, callback=None):
1231 """
1232 Start the collection loop for an adapter if the frequency > 0
1233
1234 :param callback: (callable) Function to call to collect PM data
1235 """
1236 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
1237 if callback is None:
1238 callback = self.perform_test_omci
1239
1240 if self.lc is None:
1241 self.lc = LoopingCall(callback)
1242
1243 if self.default_freq > 0:
1244 self.lc.start(interval=self.default_freq / 10)
1245
1246 def perform_test_omci(self):
1247 """
1248 Perform the initial test request
1249 """
1250 ani_g_entities = self._device.configuration.ani_g_entities
1251 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
1252 is not None else None
1253 self._entity_id = ani_g_entities_ids[0]
1254 self.logger.info('perform-test', entity_class=self._entity_class,
1255 entity_id=self._entity_id)
1256 try:
1257 frame = MEFrame(self._entity_class, self._entity_id, []).test()
1258 result = yield self._device.omci_cc.send(frame)
1259 if not result.fields['omci_message'].fields['success_code']:
1260 self.logger.info('Self-Test Submitted Successfully',
1261 code=result.fields[
1262 'omci_message'].fields['success_code'])
1263 else:
1264 raise TestFailure('Test Failure: {}'.format(
1265 result.fields['omci_message'].fields['success_code']))
1266 except TimeoutError as e:
1267 self.deferred.errback(failure.Failure(e))
1268
1269 except Exception as e:
1270 self.logger.exception('perform-test-Error', e=e,
1271 class_id=self._entity_class,
1272 entity_id=self._entity_id)
1273 self.deferred.errback(failure.Failure(e))
1274
1275 */
1276
1277 // PM related heartbeat??? !!!TODO....
1278 //self._heartbeat.enabled = True
1279
mpagenko1cc3cb42020-07-27 15:24:38 +00001280 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
1281 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
1282 * 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 +05301283 * otherwise some processing synchronization would be required - cmp. e.g TechProfile processing
mpagenko1cc3cb42020-07-27 15:24:38 +00001284 */
1285 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +00001286 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001287 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001288 if pMibUlFsm.Is(ulStDisabled) {
1289 if err := pMibUlFsm.Event(ulEvStart); err != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001290 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"device-id": dh.deviceID, "err": err})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001291 return fmt.Errorf("can't go to state starting: %s", dh.deviceID)
Himani Chawla4d908332020-08-31 12:30:20 +05301292 }
1293 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1294 //Determine ONU status and start/re-start MIB Synchronization tasks
1295 //Determine if this ONU has ever synchronized
1296 if true { //TODO: insert valid check
1297 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001298 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"device-id": dh.deviceID, "err": err})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001299 return fmt.Errorf("can't go to state resetting_mib: %s", dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001300 }
Himani Chawla4d908332020-08-31 12:30:20 +05301301 } else {
1302 if err := pMibUlFsm.Event(ulEvExamineMds); err != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001303 logger.Errorw("MibSyncFsm: Can't go to state examine_mds", log.Fields{"device-id": dh.deviceID, "err": err})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001304 return fmt.Errorf("can't go to examine_mds: %s", dh.deviceID)
Himani Chawla4d908332020-08-31 12:30:20 +05301305 }
1306 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1307 //Examine the MIB Data Sync
1308 // callbacks to be handled:
1309 // Event(ulEvSuccess)
1310 // Event(ulEvTimeout)
1311 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001312 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001313 } else {
Andrea Campanella6515c582020-10-05 11:25:00 +02001314 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current()),
mpagenko01e726e2020-10-23 09:45:29 +00001315 "device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001316 return fmt.Errorf("wrong state of MibSyncFsm: %s", dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001317 }
1318 } else {
divyadesai4d299552020-08-18 07:13:49 +00001319 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001320 return fmt.Errorf("can't execute MibSync: %s", dh.deviceID)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001321 }
1322 return nil
1323}
1324
Himani Chawla6d2ae152020-09-02 13:11:20 +05301325func (dh *deviceHandler) updateInterface(onuind *oop.OnuIndication) error {
mpagenko3af1f032020-06-10 08:53:41 +00001326 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
1327 if dh.deviceReason != "stopping-openomci" {
divyadesai4d299552020-08-18 07:13:49 +00001328 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"device-id": dh.deviceID})
mpagenko900ee4b2020-10-12 11:56:34 +00001329 //stop all running FSM processing - make use of the DH-state as mirrored in the deviceReason
1330 //here no conflict with aborted FSM's should arise as a complete OMCI initialization is assumed on ONU-Up
1331 //but that might change with some simple MDS check on ONU-Up treatment -> attention!!!
1332 if err := dh.resetFsms(); err != nil {
1333 logger.Errorw("error-updateInterface at FSM stop",
1334 log.Fields{"device-id": dh.deviceID, "error": err})
1335 // abort: system behavior is just unstable ...
1336 return err
1337 }
1338
1339 //deviceEntry stop without omciCC reset here, regarding the OMCI_CC still valid for this ONU
1340 // - in contrary to disableDevice - compare with processUniDisableStateDoneEvent
1341 //stop the device entry which resets the attached omciCC
Himani Chawla6d2ae152020-09-02 13:11:20 +05301342 pDevEntry := dh.getOnuDeviceEntry(false)
mpagenko3af1f032020-06-10 08:53:41 +00001343 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001344 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001345 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
mpagenko3af1f032020-06-10 08:53:41 +00001346 }
mpagenko900ee4b2020-10-12 11:56:34 +00001347 _ = pDevEntry.stop(context.TODO(), false)
mpagenko3af1f032020-06-10 08:53:41 +00001348
1349 //TODO!!! remove existing traffic profiles
1350 /* from py code, if TP's exist, remove them - not yet implemented
1351 self._tp = dict()
1352 # Let TP download happen again
1353 for uni_id in self._tp_service_specific_task:
1354 self._tp_service_specific_task[uni_id].clear()
1355 for uni_id in self._tech_profile_download_done:
1356 self._tech_profile_download_done[uni_id].clear()
1357 */
1358
1359 dh.disableUniPortStateUpdate()
1360
1361 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001362 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001363 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
divyadesai4d299552020-08-18 07:13:49 +00001364 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001365 // abort: system behavior is just unstable ...
1366 return err
1367 }
1368 dh.deviceReason = "stopping-openomci"
1369
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001370 logger.Debugw("call DeviceStateUpdate upon update interface", log.Fields{"ConnectStatus": voltha.ConnectStatus_UNREACHABLE,
1371 "OperStatus": voltha.OperStatus_DISCOVERED, "device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001372 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1373 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001374 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001375 logger.Errorw("error-updating-device-state unreachable-discovered",
divyadesai4d299552020-08-18 07:13:49 +00001376 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001377 // abort: system behavior is just unstable ...
1378 return err
1379 }
1380 } else {
divyadesai4d299552020-08-18 07:13:49 +00001381 logger.Debugw("updateInterface - device already stopped", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001382 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001383 return nil
1384}
1385
mpagenko900ee4b2020-10-12 11:56:34 +00001386func (dh *deviceHandler) resetFsms() error {
1387 //all possible FSM's are stopped or reset here to ensure their transition to 'disabled'
1388 //it is not sufficient to stop/reset the latest running FSM as done in previous versions
1389 // as after down/up procedures all FSM's might be active/ongoing (in theory)
1390 // and using the stop/reset event should never harm
1391
1392 pDevEntry := dh.getOnuDeviceEntry(false)
1393 if pDevEntry == nil {
1394 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
1395 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
1396 }
1397
1398 //the MibSync FSM might be active all the ONU-active time,
1399 // hence it must be stopped unconditionally
1400 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
1401 if pMibUlFsm != nil {
1402 _ = pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
1403 }
1404 //MibDownload may run
1405 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1406 if pMibDlFsm != nil {
1407 _ = pMibDlFsm.Event(dlEvReset)
1408 }
1409 //port lock/unlock FSM's may be active
1410 if dh.pUnlockStateFsm != nil {
1411 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
1412 }
1413 if dh.pLockStateFsm != nil {
1414 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
1415 }
1416 //techProfile related PonAniConfigFsm FSM may be active
1417 if dh.pOnuTP != nil {
1418 // should always be the case here
1419 // FSM stop maybe encapsulated as OnuTP method - perhaps later in context of module splitting
1420 if dh.pOnuTP.pAniConfigFsm != nil {
1421 _ = dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1422 }
1423 for _, uniPort := range dh.uniEntityMap {
mpagenko900ee4b2020-10-12 11:56:34 +00001424 // reset the possibly existing VlanConfigFsm
1425 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[uniPort.uniID]; exist {
1426 //VlanFilterFsm exists and was already started
1427 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1428 if pVlanFilterStatemachine != nil {
1429 _ = pVlanFilterStatemachine.Event(vlanEvReset)
1430 }
1431 }
1432 }
1433 }
1434 //TODO!!! care about PM/Alarm processing once started
1435 return nil
1436}
1437
Himani Chawla6d2ae152020-09-02 13:11:20 +05301438func (dh *deviceHandler) processMibDatabaseSyncEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301439 logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
1440 if !dh.reconciling {
1441 //initiate DevStateUpdate
1442 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1443 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1444 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1445 "device-id": dh.deviceID, "error": err})
1446 } else {
mpagenko01e726e2020-10-23 09:45:29 +00001447 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301448 }
1449 } else {
1450 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
1451 log.Fields{"device-id": dh.deviceID})
1452 }
1453 //set internal state anyway - as it was done
1454 dh.deviceReason = "discovery-mibsync-complete"
1455
1456 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Himani Chawla6d2ae152020-09-02 13:11:20 +05301457 pDevEntry := dh.getOnuDeviceEntry(false)
1458 if unigInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301459 for _, mgmtEntityID := range unigInstKeys {
1460 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
1461 "device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301462 dh.addUniPort(mgmtEntityID, i, uniPPTP)
Himani Chawla26e555c2020-08-31 12:30:20 +05301463 i++
1464 }
1465 } else {
1466 logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
1467 }
Himani Chawla6d2ae152020-09-02 13:11:20 +05301468 if veipInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301469 for _, mgmtEntityID := range veipInstKeys {
1470 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
1471 "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301472 dh.addUniPort(mgmtEntityID, i, uniVEIP)
Himani Chawla26e555c2020-08-31 12:30:20 +05301473 i++
1474 }
1475 } else {
1476 logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
1477 }
1478 if i == 0 {
1479 logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
1480 }
1481
1482 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1483 * left the code here as comment in case such processing should prove needed unexpectedly
1484 // Init Uni Ports to Admin locked state
1485 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1486 // *** should generate UniLockStateDone event *****
1487 if dh.pLockStateFsm == nil {
1488 dh.createUniLockFsm(true, UniLockStateDone)
1489 } else { //LockStateFSM already init
1490 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1491 dh.runUniLockFsm(true)
1492 }
1493 }
1494 case UniLockStateDone:
1495 {
1496 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
1497 * lockState processing commented out
1498 */
1499 /* Mib download procedure -
1500 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1501 */
1502 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1503 if pMibDlFsm != nil {
1504 if pMibDlFsm.Is(dlStDisabled) {
1505 if err := pMibDlFsm.Event(dlEvStart); err != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001506 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"device-id": dh.deviceID, "err": err})
Himani Chawla26e555c2020-08-31 12:30:20 +05301507 // maybe try a FSM reset and then again ... - TODO!!!
1508 } else {
1509 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1510 // maybe use more specific states here for the specific download steps ...
1511 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001512 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"device-id": dh.deviceID, "err": err})
Himani Chawla26e555c2020-08-31 12:30:20 +05301513 } else {
1514 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1515 //Begin MIB data download (running autonomously)
1516 }
1517 }
1518 } else {
Andrea Campanella6515c582020-10-05 11:25:00 +02001519 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current()),
mpagenko01e726e2020-10-23 09:45:29 +00001520 "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301521 // maybe try a FSM reset and then again ... - TODO!!!
1522 }
1523 /***** Mib download started */
1524 } else {
1525 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
1526 }
1527}
1528
Himani Chawla6d2ae152020-09-02 13:11:20 +05301529func (dh *deviceHandler) processMibDownloadDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301530 logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
1531 //initiate DevStateUpdate
1532 if !dh.reconciling {
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001533 logger.Debugw("call DeviceStateUpdate upon mib-download done", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
1534 "OperStatus": voltha.OperStatus_ACTIVE, "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301535 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1536 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1537 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1538 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1539 } else {
1540 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
1541 }
1542 } else {
1543 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
1544 log.Fields{"device-id": dh.deviceID})
1545 }
1546 if !dh.reconciling {
1547 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1548 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1549 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1550 log.Fields{"device-id": dh.deviceID, "error": err})
1551 } else {
1552 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
1553 }
1554 } else {
1555 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
1556 log.Fields{"device-id": dh.deviceID})
1557 }
1558 //set internal state anyway - as it was done
1559 dh.deviceReason = "initial-mib-downloaded"
1560 // *** should generate UniUnlockStateDone event *****
1561 if dh.pUnlockStateFsm == nil {
1562 dh.createUniLockFsm(false, UniUnlockStateDone)
1563 } else { //UnlockStateFSM already init
Himani Chawla6d2ae152020-09-02 13:11:20 +05301564 dh.pUnlockStateFsm.setSuccessEvent(UniUnlockStateDone)
Himani Chawla26e555c2020-08-31 12:30:20 +05301565 dh.runUniLockFsm(false)
1566 }
1567}
1568
Himani Chawla6d2ae152020-09-02 13:11:20 +05301569func (dh *deviceHandler) processUniUnlockStateDoneEvent(devEvent OnuDeviceEvent) {
mpagenko900ee4b2020-10-12 11:56:34 +00001570 dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Himani Chawla26e555c2020-08-31 12:30:20 +05301571
1572 if !dh.reconciling {
1573 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
1574 raisedTs := time.Now().UnixNano()
1575 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1576 } else {
1577 logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
1578 log.Fields{"device-id": dh.deviceID})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301579 go dh.reconcileDeviceTechProf()
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001580 // reconcilement will be continued after ani config is done
Himani Chawla26e555c2020-08-31 12:30:20 +05301581 }
1582}
1583
mpagenko900ee4b2020-10-12 11:56:34 +00001584func (dh *deviceHandler) processUniDisableStateDoneEvent(devEvent OnuDeviceEvent) {
1585 logger.Debugw("DeviceStateUpdate upon disable", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
1586 "OperStatus": voltha.OperStatus_UNKNOWN, "device-id": dh.deviceID})
1587 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(),
1588 dh.deviceID, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1589 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1590 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1591 }
1592
1593 logger.Debugw("DeviceReasonUpdate upon re-enable", log.Fields{
1594 "reason": "omci-admin-lock", "device-id": dh.deviceID})
1595 // DeviceReason to update acc.to modified py code as per beginning of Sept 2020
1596 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
1597 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1598 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
1599 }
1600 dh.deviceReason = "omci-admin-lock"
1601
1602 //transfer the modified logical uni port state
1603 dh.disableUniPortStateUpdate()
1604
1605 //stop the device entry which resets the attached omciCC
1606 pDevEntry := dh.getOnuDeviceEntry(false)
1607 if pDevEntry == nil {
1608 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
1609 return
1610 }
1611 _ = pDevEntry.stop(context.TODO(), true) //stop deviceEntry with omciCC reset
mpagenko900ee4b2020-10-12 11:56:34 +00001612}
1613
1614func (dh *deviceHandler) processUniEnableStateDoneEvent(devEvent OnuDeviceEvent) {
1615 logger.Debugw("DeviceStateUpdate upon re-enable", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
1616 "OperStatus": voltha.OperStatus_ACTIVE, "device-id": dh.deviceID})
1617 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
1618 voltha.OperStatus_ACTIVE); err != nil {
1619 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1620 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1621 }
1622
1623 logger.Debugw("DeviceReasonUpdate upon re-enable", log.Fields{
1624 "reason": "onu-reenabled", "device-id": dh.deviceID})
1625 // DeviceReason to update acc.to modified py code as per beginning of Sept 2020
1626 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "onu-reenabled"); err != nil {
1627 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1628 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
1629 }
1630 dh.deviceReason = "onu-reenabled"
1631
1632 //transfer the modified logical uni port state
1633 dh.enableUniPortStateUpdate()
1634}
1635
Himani Chawla6d2ae152020-09-02 13:11:20 +05301636func (dh *deviceHandler) processOmciAniConfigDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301637 logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
1638 // attention: the device reason update is done based on ONU-UNI-Port related activity
1639 // - which may cause some inconsistency
1640 if dh.deviceReason != "tech-profile-config-download-success" {
1641 // which may be the case from some previous actvity on another UNI Port of the ONU
1642 if !dh.reconciling {
1643 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1644 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1645 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1646 log.Fields{"device-id": dh.deviceID, "error": err})
1647 } else {
1648 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1649 log.Fields{"device-id": dh.deviceID})
1650 }
1651 } else {
1652 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
1653 log.Fields{"device-id": dh.deviceID})
1654 }
1655 //set internal state anyway - as it was done
1656 dh.deviceReason = "tech-profile-config-download-success"
1657 }
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001658 if dh.reconciling {
1659 go dh.reconcileDeviceFlowConfig()
1660 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301661}
1662
Himani Chawla6d2ae152020-09-02 13:11:20 +05301663func (dh *deviceHandler) processOmciVlanFilterDoneEvent(devEvent OnuDeviceEvent) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301664 logger.Debugw("OmciVlanFilterDone event received",
1665 log.Fields{"device-id": dh.deviceID})
1666 // attention: the device reason update is done based on ONU-UNI-Port related activity
1667 // - which may cause some inconsistency
1668 // yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
1669
1670 if dh.deviceReason != "omci-flows-pushed" {
1671 // which may be the case from some previous actvity on another UNI Port of the ONU
1672 // or even some previous flow add activity on the same port
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001673 if !dh.reconciling {
1674 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
1675 logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
1676 log.Fields{"device-id": dh.deviceID, "error": err})
1677 } else {
1678 logger.Infow("updated dev reason to ''omci-flows-pushed'",
1679 log.Fields{"device-id": dh.deviceID})
1680 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301681 } else {
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001682 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to omci-flows-pushed",
Himani Chawla26e555c2020-08-31 12:30:20 +05301683 log.Fields{"device-id": dh.deviceID})
1684 }
1685 //set internal state anyway - as it was done
1686 dh.deviceReason = "omci-flows-pushed"
Holger Hildebrandt47555e72020-09-21 11:07:24 +00001687
1688 if dh.reconciling {
1689 go dh.reconcileMetrics()
1690 }
Himani Chawla26e555c2020-08-31 12:30:20 +05301691 }
1692}
1693
Himani Chawla6d2ae152020-09-02 13:11:20 +05301694//deviceProcStatusUpdate evaluates possible processing events and initiates according next activities
1695func (dh *deviceHandler) deviceProcStatusUpdate(devEvent OnuDeviceEvent) {
Himani Chawla4d908332020-08-31 12:30:20 +05301696 switch devEvent {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001697 case MibDatabaseSync:
1698 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301699 dh.processMibDatabaseSyncEvent(devEvent)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001700 }
1701 case MibDownloadDone:
1702 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301703 dh.processMibDownloadDoneEvent(devEvent)
1704
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001705 }
1706 case UniUnlockStateDone:
1707 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301708 dh.processUniUnlockStateDoneEvent(devEvent)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001709
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001710 }
mpagenko900ee4b2020-10-12 11:56:34 +00001711 case UniEnableStateDone:
1712 {
1713 dh.processUniEnableStateDoneEvent(devEvent)
1714
1715 }
1716 case UniDisableStateDone:
1717 {
1718 dh.processUniDisableStateDoneEvent(devEvent)
1719
1720 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001721 case OmciAniConfigDone:
1722 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301723 dh.processOmciAniConfigDoneEvent(devEvent)
1724
mpagenko3dbcdd22020-07-22 07:38:45 +00001725 }
mpagenkodff5dda2020-08-28 11:52:01 +00001726 case OmciVlanFilterDone:
1727 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301728 dh.processOmciVlanFilterDoneEvent(devEvent)
mpagenkodff5dda2020-08-28 11:52:01 +00001729
mpagenkodff5dda2020-08-28 11:52:01 +00001730 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001731 default:
1732 {
Andrea Campanellaab7b6a52020-10-06 16:17:13 +02001733 logger.Debugw("unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": devEvent})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001734 }
1735 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001736}
1737
Himani Chawla6d2ae152020-09-02 13:11:20 +05301738func (dh *deviceHandler) addUniPort(aUniInstNo uint16, aUniID uint8, aPortType uniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001739 // parameters are IntfId, OnuId, uniId
Himani Chawla6d2ae152020-09-02 13:11:20 +05301740 uniNo := mkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
Himani Chawla4d908332020-08-31 12:30:20 +05301741 uint32(aUniID))
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001742 if _, present := dh.uniEntityMap[uniNo]; present {
Himani Chawla4d908332020-08-31 12:30:20 +05301743 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001744 } else {
Himani Chawla4d908332020-08-31 12:30:20 +05301745 //with arguments aUniID, a_portNo, aPortType
Himani Chawla6d2ae152020-09-02 13:11:20 +05301746 pUniPort := newOnuUniPort(aUniID, uniNo, aUniInstNo, aPortType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001747 if pUniPort == nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301748 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001749 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001750 //store UniPort with the System-PortNumber key
1751 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001752 if !dh.reconciling {
1753 // create announce the UniPort to the core as VOLTHA Port object
Himani Chawla6d2ae152020-09-02 13:11:20 +05301754 if err := pUniPort.createVolthaPort(dh); err == nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001755 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1756 } //error logging already within UniPort method
1757 } else {
1758 logger.Debugw("reconciling - onuUniPort already added", log.Fields{"for PortNo": uniNo, "device-id": dh.deviceID})
1759 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001760 }
1761 }
1762}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001763
mpagenko3af1f032020-06-10 08:53:41 +00001764// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05301765func (dh *deviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001766 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
Himani Chawla4d908332020-08-31 12:30:20 +05301767 // but towards core only the first port active state is signaled
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001768 // with following remark:
1769 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1770 // # load on the core
1771
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001772 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001773
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001774 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001775 // only if this port is validated for operState transfer
Himani Chawla6d2ae152020-09-02 13:11:20 +05301776 if (1<<uniPort.uniID)&activeUniPortStateUpdateMask == (1 << uniPort.uniID) {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001777 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301778 uniPort.setOperState(vc.OperStatus_ACTIVE)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001779 if !dh.reconciling {
1780 //maybe also use getter functions on uniPort - perhaps later ...
1781 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1782 } else {
Andrea Campanellaab7b6a52020-10-06 16:17:13 +02001783 //TODO there is no retry mechanism, return error
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001784 logger.Debugw("reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
1785 }
mpagenko3af1f032020-06-10 08:53:41 +00001786 }
1787 }
1788}
1789
1790// Disable UniPortState and update core port state accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05301791func (dh *deviceHandler) disableUniPortStateUpdate() {
mpagenko3af1f032020-06-10 08:53:41 +00001792 // compare enableUniPortStateUpdate() above
1793 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1794 for uniNo, uniPort := range dh.uniEntityMap {
1795 // only if this port is validated for operState transfer
Himani Chawla6d2ae152020-09-02 13:11:20 +05301796 if (1<<uniPort.uniID)&activeUniPortStateUpdateMask == (1 << uniPort.uniID) {
mpagenko3af1f032020-06-10 08:53:41 +00001797 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
Himani Chawla6d2ae152020-09-02 13:11:20 +05301798 uniPort.setOperState(vc.OperStatus_UNKNOWN)
mpagenko3af1f032020-06-10 08:53:41 +00001799 //maybe also use getter functions on uniPort - perhaps later ...
1800 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001801 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001802 }
1803}
1804
1805// ONU_Active/Inactive announcement on system KAFKA bus
1806// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
Himani Chawla6d2ae152020-09-02 13:11:20 +05301807func (dh *deviceHandler) sendOnuOperStateEvent(aOperState vc.OperStatus_Types, aDeviceID string, raisedTs int64) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001808 var de voltha.DeviceEvent
1809 eventContext := make(map[string]string)
1810 //Populating event context
1811 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
Himani Chawla4d908332020-08-31 12:30:20 +05301812 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentID, dh.parentID)
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001813 if err != nil || parentDevice == nil {
1814 logger.Errorw("Failed to fetch parent device for OnuEvent",
Himani Chawla4d908332020-08-31 12:30:20 +05301815 log.Fields{"parentID": dh.parentID, "err": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001816 }
1817 oltSerialNumber := parentDevice.SerialNumber
1818
1819 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1820 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1821 eventContext["serial-number"] = dh.device.SerialNumber
1822 eventContext["olt_serial_number"] = oltSerialNumber
Himani Chawla4d908332020-08-31 12:30:20 +05301823 eventContext["device_id"] = aDeviceID
1824 eventContext["registration_id"] = aDeviceID //py: string(device_id)??
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001825 logger.Debugw("prepare ONU_ACTIVATED event",
mpagenko01e726e2020-10-23 09:45:29 +00001826 log.Fields{"device-id": aDeviceID, "EventContext": eventContext})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001827
1828 /* Populating device event body */
1829 de.Context = eventContext
Himani Chawla4d908332020-08-31 12:30:20 +05301830 de.ResourceId = aDeviceID
1831 if aOperState == voltha.OperStatus_ACTIVE {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001832 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1833 de.Description = fmt.Sprintf("%s Event - %s - %s",
1834 cEventObjectType, cOnuActivatedEvent, "Raised")
1835 } else {
1836 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1837 de.Description = fmt.Sprintf("%s Event - %s - %s",
1838 cEventObjectType, cOnuActivatedEvent, "Cleared")
1839 }
1840 /* Send event to KAFKA */
1841 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1842 logger.Warnw("could not send ONU_ACTIVATED event",
Himani Chawla4d908332020-08-31 12:30:20 +05301843 log.Fields{"device-id": aDeviceID, "error": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001844 }
1845 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
Himani Chawla4d908332020-08-31 12:30:20 +05301846 log.Fields{"device-id": aDeviceID, "with-EventName": de.DeviceEventName})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001847}
1848
Himani Chawla4d908332020-08-31 12:30:20 +05301849// createUniLockFsm initializes and runs the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Himani Chawla6d2ae152020-09-02 13:11:20 +05301850func (dh *deviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001851 chLSFsm := make(chan Message, 2048)
1852 var sFsmName string
Himani Chawla4d908332020-08-31 12:30:20 +05301853 if aAdminState {
divyadesai4d299552020-08-18 07:13:49 +00001854 logger.Infow("createLockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001855 sFsmName = "LockStateFSM"
1856 } else {
divyadesai4d299552020-08-18 07:13:49 +00001857 logger.Infow("createUnlockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001858 sFsmName = "UnLockStateFSM"
1859 }
mpagenko3af1f032020-06-10 08:53:41 +00001860
Himani Chawla6d2ae152020-09-02 13:11:20 +05301861 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenko3af1f032020-06-10 08:53:41 +00001862 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001863 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001864 return
1865 }
Himani Chawla6d2ae152020-09-02 13:11:20 +05301866 pLSFsm := newLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandt8165eda2020-09-24 09:39:24 +00001867 sFsmName, dh, chLSFsm)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001868 if pLSFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301869 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001870 dh.pLockStateFsm = pLSFsm
1871 } else {
1872 dh.pUnlockStateFsm = pLSFsm
1873 }
1874 dh.runUniLockFsm(aAdminState)
1875 } else {
divyadesai4d299552020-08-18 07:13:49 +00001876 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001877 }
1878}
1879
1880// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Himani Chawla6d2ae152020-09-02 13:11:20 +05301881func (dh *deviceHandler) runUniLockFsm(aAdminState bool) {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001882 /* Uni Port lock/unlock procedure -
1883 ***** should run via 'adminDone' state and generate the argument requested event *****
1884 */
1885 var pLSStatemachine *fsm.FSM
Himani Chawla4d908332020-08-31 12:30:20 +05301886 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001887 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1888 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1889 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001890 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301891 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001892 }
1893 } else {
1894 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1895 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1896 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001897 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301898 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001899 }
1900 }
1901 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001902 if pLSStatemachine.Is(uniStDisabled) {
1903 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001904 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1905 // maybe try a FSM reset and then again ... - TODO!!!
1906 } else {
1907 /***** LockStateFSM started */
1908 logger.Debugw("LockStateFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001909 "state": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001910 }
1911 } else {
1912 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001913 "have": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001914 // maybe try a FSM reset and then again ... - TODO!!!
1915 }
1916 } else {
divyadesai4d299552020-08-18 07:13:49 +00001917 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001918 // maybe try a FSM reset and then again ... - TODO!!!
1919 }
1920}
1921
Himani Chawla6d2ae152020-09-02 13:11:20 +05301922//setBackend provides a DB backend for the specified path on the existing KV client
1923func (dh *deviceHandler) setBackend(aBasePathKvStore string) *db.Backend {
mpagenkoaf801632020-07-03 10:00:42 +00001924 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1925 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
divyadesai4d299552020-08-18 07:13:49 +00001926 "BasePathKvStore": aBasePathKvStore, "device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +00001927 kvbackend := &db.Backend{
1928 Client: dh.pOpenOnuAc.kvClient,
1929 StoreType: dh.pOpenOnuAc.KVStoreType,
1930 /* address config update acc. to [VOL-2736] */
1931 Address: addr,
1932 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1933 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001934
mpagenkoaf801632020-07-03 10:00:42 +00001935 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001936}
Himani Chawla6d2ae152020-09-02 13:11:20 +05301937func (dh *deviceHandler) getFlowOfbFields(apFlowItem *ofp.OfpFlowStats, loMatchVlan *uint16,
Himani Chawla26e555c2020-08-31 12:30:20 +05301938 loAddPcp *uint8, loIPProto *uint32) {
mpagenkodff5dda2020-08-28 11:52:01 +00001939
mpagenkodff5dda2020-08-28 11:52:01 +00001940 for _, field := range flow.GetOfbFields(apFlowItem) {
1941 switch field.Type {
1942 case of.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
1943 {
mpagenko01e726e2020-10-23 09:45:29 +00001944 logger.Debugw("flow type EthType", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001945 "EthType": strconv.FormatInt(int64(field.GetEthType()), 16)})
1946 }
mpagenko01e726e2020-10-23 09:45:29 +00001947 /* TT related temporary workaround - should not be needed anymore
mpagenkodff5dda2020-08-28 11:52:01 +00001948 case of.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
1949 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301950 *loIPProto = field.GetIpProto()
mpagenko01e726e2020-10-23 09:45:29 +00001951 logger.Debugw("flow type IpProto", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301952 "IpProto": strconv.FormatInt(int64(*loIPProto), 16)})
1953 if *loIPProto == 2 {
mpagenkodff5dda2020-08-28 11:52:01 +00001954 // some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
1955 // avoids installing invalid EVTOCD rule
mpagenko01e726e2020-10-23 09:45:29 +00001956 logger.Debugw("flow type IpProto 2: TT workaround: ignore flow",
1957 log.Fields{"device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05301958 return
mpagenkodff5dda2020-08-28 11:52:01 +00001959 }
1960 }
mpagenko01e726e2020-10-23 09:45:29 +00001961 */
mpagenkodff5dda2020-08-28 11:52:01 +00001962 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
1963 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301964 *loMatchVlan = uint16(field.GetVlanVid())
mpagenkodff5dda2020-08-28 11:52:01 +00001965 loMatchVlanMask := uint16(field.GetVlanVidMask())
Himani Chawla26e555c2020-08-31 12:30:20 +05301966 if !(*loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) &&
mpagenkodff5dda2020-08-28 11:52:01 +00001967 loMatchVlanMask == uint16(of.OfpVlanId_OFPVID_PRESENT)) {
Himani Chawla26e555c2020-08-31 12:30:20 +05301968 *loMatchVlan = *loMatchVlan & 0xFFF // not transparent: copy only ID bits
mpagenkodff5dda2020-08-28 11:52:01 +00001969 }
mpagenko01e726e2020-10-23 09:45:29 +00001970 logger.Debugw("flow field type", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05301971 "VID": strconv.FormatInt(int64(*loMatchVlan), 16)})
mpagenkodff5dda2020-08-28 11:52:01 +00001972 }
1973 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
1974 {
Himani Chawla26e555c2020-08-31 12:30:20 +05301975 *loAddPcp = uint8(field.GetVlanPcp())
mpagenko01e726e2020-10-23 09:45:29 +00001976 logger.Debugw("flow field type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001977 "PCP": loAddPcp})
1978 }
1979 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
1980 {
mpagenko01e726e2020-10-23 09:45:29 +00001981 logger.Debugw("flow field type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001982 "UDP-DST": strconv.FormatInt(int64(field.GetUdpDst()), 16)})
1983 }
1984 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
1985 {
mpagenko01e726e2020-10-23 09:45:29 +00001986 logger.Debugw("flow field type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001987 "UDP-SRC": strconv.FormatInt(int64(field.GetUdpSrc()), 16)})
1988 }
1989 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
1990 {
mpagenko01e726e2020-10-23 09:45:29 +00001991 logger.Debugw("flow field type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001992 "IPv4-DST": field.GetIpv4Dst()})
1993 }
1994 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC:
1995 {
mpagenko01e726e2020-10-23 09:45:29 +00001996 logger.Debugw("flow field type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001997 "IPv4-SRC": field.GetIpv4Src()})
1998 }
1999 case of.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
2000 {
mpagenko01e726e2020-10-23 09:45:29 +00002001 logger.Debugw("flow field type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00002002 "Metadata": field.GetTableMetadata()})
2003 }
2004 /*
2005 default:
2006 {
2007 //all other entires ignored
2008 }
2009 */
2010 }
2011 } //for all OfbFields
Himani Chawla26e555c2020-08-31 12:30:20 +05302012}
mpagenkodff5dda2020-08-28 11:52:01 +00002013
Himani Chawla6d2ae152020-09-02 13:11:20 +05302014func (dh *deviceHandler) getFlowActions(apFlowItem *ofp.OfpFlowStats, loSetPcp *uint8, loSetVlan *uint16) {
mpagenkodff5dda2020-08-28 11:52:01 +00002015 for _, action := range flow.GetActions(apFlowItem) {
2016 switch action.Type {
2017 /* not used:
2018 case of.OfpActionType_OFPAT_OUTPUT:
2019 {
mpagenko01e726e2020-10-23 09:45:29 +00002020 logger.Debugw("flow action type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00002021 "Output": action.GetOutput()})
2022 }
2023 */
2024 case of.OfpActionType_OFPAT_PUSH_VLAN:
2025 {
mpagenko01e726e2020-10-23 09:45:29 +00002026 logger.Debugw("flow action type", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00002027 "PushEthType": strconv.FormatInt(int64(action.GetPush().Ethertype), 16)})
2028 }
2029 case of.OfpActionType_OFPAT_SET_FIELD:
2030 {
2031 pActionSetField := action.GetSetField()
2032 if pActionSetField.Field.OxmClass != of.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
mpagenko01e726e2020-10-23 09:45:29 +00002033 logger.Warnw("flow action SetField invalid OxmClass (ignored)", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00002034 "OxcmClass": pActionSetField.Field.OxmClass})
2035 }
2036 if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Himani Chawla26e555c2020-08-31 12:30:20 +05302037 *loSetVlan = uint16(pActionSetField.Field.GetOfbField().GetVlanVid())
mpagenko01e726e2020-10-23 09:45:29 +00002038 logger.Debugw("flow Set VLAN from SetField action", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05302039 "SetVlan": strconv.FormatInt(int64(*loSetVlan), 16)})
mpagenkodff5dda2020-08-28 11:52:01 +00002040 } else if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
Himani Chawla26e555c2020-08-31 12:30:20 +05302041 *loSetPcp = uint8(pActionSetField.Field.GetOfbField().GetVlanPcp())
mpagenko01e726e2020-10-23 09:45:29 +00002042 logger.Debugw("flow Set PCP from SetField action", log.Fields{"device-id": dh.deviceID,
Himani Chawla26e555c2020-08-31 12:30:20 +05302043 "SetPcp": *loSetPcp})
mpagenkodff5dda2020-08-28 11:52:01 +00002044 } else {
mpagenko01e726e2020-10-23 09:45:29 +00002045 logger.Warnw("flow action SetField invalid FieldType", log.Fields{"device-id": dh.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00002046 "Type": pActionSetField.Field.GetOfbField().Type})
2047 }
2048 }
2049 /*
2050 default:
2051 {
2052 //all other entires ignored
2053 }
2054 */
2055 }
2056 } //for all Actions
Himani Chawla26e555c2020-08-31 12:30:20 +05302057}
2058
2059//addFlowItemToUniPort parses the actual flow item to add it to the UniPort
Himani Chawla6d2ae152020-09-02 13:11:20 +05302060func (dh *deviceHandler) addFlowItemToUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *onuUniPort) error {
Himani Chawla26e555c2020-08-31 12:30:20 +05302061 var loSetVlan uint16 = uint16(of.OfpVlanId_OFPVID_NONE) //noValidEntry
2062 var loMatchVlan uint16 = uint16(of.OfpVlanId_OFPVID_PRESENT) //reserved VLANID entry
2063 var loAddPcp, loSetPcp uint8
2064 var loIPProto uint32
2065 /* the TechProfileId is part of the flow Metadata - compare also comment within
2066 * OLT-Adapter:openolt_flowmgr.go
2067 * Metadata 8 bytes:
2068 * Most Significant 2 Bytes = Inner VLAN
2069 * Next 2 Bytes = Tech Profile ID(TPID)
2070 * Least Significant 4 Bytes = Port ID
2071 * Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2072 * subscriber related flows.
2073 */
2074
2075 metadata := flow.GetMetadataFromWriteMetadataAction(apFlowItem)
2076 if metadata == 0 {
mpagenko01e726e2020-10-23 09:45:29 +00002077 logger.Debugw("flow-add invalid metadata - abort",
Himani Chawla26e555c2020-08-31 12:30:20 +05302078 log.Fields{"device-id": dh.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00002079 return fmt.Errorf("flow-add invalid metadata: %s", dh.deviceID)
Himani Chawla26e555c2020-08-31 12:30:20 +05302080 }
2081 loTpID := flow.GetTechProfileIDFromWriteMetaData(metadata)
mpagenko01e726e2020-10-23 09:45:29 +00002082 loCookie := apFlowItem.GetCookie()
2083 loCookieSlice := []uint64{loCookie}
2084 logger.Debugw("flow-add base indications", log.Fields{"device-id": dh.deviceID,
2085 "TechProf-Id": loTpID, "cookie": loCookie})
Himani Chawla26e555c2020-08-31 12:30:20 +05302086
2087 dh.getFlowOfbFields(apFlowItem, &loMatchVlan, &loAddPcp, &loIPProto)
mpagenko01e726e2020-10-23 09:45:29 +00002088 /* TT related temporary workaround - should not be needed anymore
Himani Chawla26e555c2020-08-31 12:30:20 +05302089 if loIPProto == 2 {
2090 // some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
2091 // avoids installing invalid EVTOCD rule
mpagenko01e726e2020-10-23 09:45:29 +00002092 logger.Debugw("flow-add type IpProto 2: TT workaround: ignore flow",
2093 log.Fields{"device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05302094 return nil
2095 }
mpagenko01e726e2020-10-23 09:45:29 +00002096 */
Himani Chawla26e555c2020-08-31 12:30:20 +05302097 dh.getFlowActions(apFlowItem, &loSetPcp, &loSetVlan)
mpagenkodff5dda2020-08-28 11:52:01 +00002098
2099 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
mpagenko01e726e2020-10-23 09:45:29 +00002100 logger.Errorw("flow-add aborted - SetVlanId undefined, but MatchVid set", log.Fields{
mpagenkodff5dda2020-08-28 11:52:01 +00002101 "device-id": dh.deviceID, "UniPort": apUniPort.portNo,
2102 "set_vid": strconv.FormatInt(int64(loSetVlan), 16),
2103 "match_vid": strconv.FormatInt(int64(loMatchVlan), 16)})
2104 //TODO!!: Use DeviceId within the error response to rwCore
2105 // likewise also in other error response cases to calling components as requested in [VOL-3458]
mpagenko01e726e2020-10-23 09:45:29 +00002106 return fmt.Errorf("flow-add Set/Match VlanId inconsistent: %s", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002107 }
2108 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) {
mpagenko01e726e2020-10-23 09:45:29 +00002109 logger.Debugw("flow-add vlan-any/copy", log.Fields{"device-id": dh.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00002110 loSetVlan = loMatchVlan //both 'transparent' (copy any)
2111 } else {
2112 //looks like OMCI value 4097 (copyFromOuter - for Uni double tagged) is not supported here
2113 if loSetVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
2114 // not set to transparent
Himani Chawla26e555c2020-08-31 12:30:20 +05302115 loSetVlan &= 0x0FFF //mask VID bits as prerequisite for vlanConfigFsm
mpagenkodff5dda2020-08-28 11:52:01 +00002116 }
mpagenko01e726e2020-10-23 09:45:29 +00002117 logger.Debugw("flow-add vlan-set", log.Fields{"device-id": dh.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00002118 }
Himani Chawla26e555c2020-08-31 12:30:20 +05302119 if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
mpagenko01e726e2020-10-23 09:45:29 +00002120 return dh.UniVlanConfigFsmMap[apUniPort.uniID].SetUniFlowParams(loTpID, loCookieSlice,
2121 loMatchVlan, loSetVlan, loSetPcp)
mpagenkodff5dda2020-08-28 11:52:01 +00002122 }
mpagenko01e726e2020-10-23 09:45:29 +00002123 return dh.createVlanFilterFsm(apUniPort, loTpID, loCookieSlice,
2124 loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterDone)
2125}
2126
2127//removeFlowItemFromUniPort parses the actual flow item to remove it from the UniPort
2128func (dh *deviceHandler) removeFlowItemFromUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *onuUniPort) error {
2129 //optimization and assumption: the flow cookie uniquely identifies the flow and with that the internal rule
2130 //hence only the cookie is used here to find the relevant flow and possibly remove the rule
2131 //no extra check is done on the rule parameters
2132 //accordingly the removal is done only once - for the first found flow with that cookie, even though
2133 // at flow creation is not assured, that the same cookie is not configured for different flows - just assumed
2134 //additionally it is assumed here, that removal can only be done for one cookie per flow in a sequence (different
2135 // from addFlow - where at reconcilement multiple cookies per flow ) can be configured in one sequence)
2136 // - some possible 'delete-all' sequence would have be implemented separately (where the cookies are don't care anyway)
2137 loCookie := apFlowItem.GetCookie()
2138 logger.Debugw("flow-remove base indications", log.Fields{"device-id": dh.deviceID, "cookie": loCookie})
2139
2140 /* TT related temporary workaround - should not be needed anymore
2141 for _, field := range flow.GetOfbFields(apFlowItem) {
2142 if field.Type == of.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO {
2143 loIPProto := field.GetIpProto()
2144 logger.Debugw("flow type IpProto", log.Fields{"device-id": dh.deviceID,
2145 "IpProto": strconv.FormatInt(int64(loIPProto), 16)})
2146 if loIPProto == 2 {
2147 // some workaround for TT workflow on proto == 2 (IGMP trap) -> the flow was not added, no need to remove
2148 logger.Debugw("flow-remove type IpProto 2: TT workaround: ignore flow",
2149 log.Fields{"device-id": dh.deviceID})
2150 return nil
2151 }
2152 }
2153 } //for all OfbFields
2154 */
2155
2156 if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
2157 return dh.UniVlanConfigFsmMap[apUniPort.uniID].RemoveUniFlowParams(loCookie)
2158 }
2159 logger.Warnw("flow-remove called, but no flow is configured (no VlanConfigFsm)",
2160 log.Fields{"device-id": dh.deviceID})
2161 //but as we regard the flow as not existing = removed we respond just ok
2162 return nil
mpagenkodff5dda2020-08-28 11:52:01 +00002163}
2164
Himani Chawla26e555c2020-08-31 12:30:20 +05302165// createVlanFilterFsm initializes and runs the VlanFilter FSM to transfer OMCI related VLAN config
mpagenko01e726e2020-10-23 09:45:29 +00002166func (dh *deviceHandler) createVlanFilterFsm(apUniPort *onuUniPort, aTpID uint16, aCookieSlice []uint64,
2167 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8, aDevEvent OnuDeviceEvent) error {
mpagenkodff5dda2020-08-28 11:52:01 +00002168 chVlanFilterFsm := make(chan Message, 2048)
2169
Himani Chawla6d2ae152020-09-02 13:11:20 +05302170 pDevEntry := dh.getOnuDeviceEntry(true)
mpagenkodff5dda2020-08-28 11:52:01 +00002171 if pDevEntry == nil {
2172 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05302173 return fmt.Errorf("no valid OnuDevice for device-id %x - aborting", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002174 }
2175
2176 pVlanFilterFsm := NewUniVlanConfigFsm(dh, pDevEntry.PDevOmciCC, apUniPort, dh.pOnuTP,
mpagenko01e726e2020-10-23 09:45:29 +00002177 pDevEntry.pOnuDB, aTpID, aDevEvent, "UniVlanConfigFsm", chVlanFilterFsm,
2178 dh.pOpenOnuAc.AcceptIncrementalEvto, aCookieSlice, aMatchVlan, aSetVlan, aSetPcp)
mpagenkodff5dda2020-08-28 11:52:01 +00002179 if pVlanFilterFsm != nil {
Himani Chawla26e555c2020-08-31 12:30:20 +05302180 dh.UniVlanConfigFsmMap[apUniPort.uniID] = pVlanFilterFsm
mpagenkodff5dda2020-08-28 11:52:01 +00002181 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
2182 if pVlanFilterStatemachine != nil {
2183 if pVlanFilterStatemachine.Is(vlanStDisabled) {
2184 if err := pVlanFilterStatemachine.Event(vlanEvStart); err != nil {
2185 logger.Warnw("UniVlanConfigFsm: can't start", log.Fields{"err": err})
Himani Chawla26e555c2020-08-31 12:30:20 +05302186 return fmt.Errorf("can't start UniVlanConfigFsm for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002187 }
Himani Chawla26e555c2020-08-31 12:30:20 +05302188 /***** UniVlanConfigFsm started */
2189 logger.Debugw("UniVlanConfigFsm started", log.Fields{
2190 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
2191 "UniPort": apUniPort.portNo})
mpagenkodff5dda2020-08-28 11:52:01 +00002192 } else {
2193 logger.Warnw("wrong state of UniVlanConfigFsm - want: disabled", log.Fields{
2194 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05302195 return fmt.Errorf("uniVlanConfigFsm not in expected disabled state for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002196 }
2197 } else {
2198 logger.Errorw("UniVlanConfigFsm StateMachine invalid - cannot be executed!!", log.Fields{
2199 "device-id": dh.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +05302200 return fmt.Errorf("uniVlanConfigFsm invalid for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002201 }
2202 } else {
2203 logger.Errorw("UniVlanConfigFsm could not be created - abort!!", log.Fields{
2204 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
Himani Chawla26e555c2020-08-31 12:30:20 +05302205 return fmt.Errorf("uniVlanConfigFsm could not be created for device-id %x", dh.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002206 }
2207 return nil
2208}
2209
2210//verifyUniVlanConfigRequest checks on existence of flow configuration and starts it accordingly
Himani Chawla6d2ae152020-09-02 13:11:20 +05302211func (dh *deviceHandler) verifyUniVlanConfigRequest(apUniPort *onuUniPort) {
mpagenkodff5dda2020-08-28 11:52:01 +00002212 //TODO!! verify and start pending flow configuration
2213 //some pending config request my exist in case the UniVlanConfig FSM was already started - with internal data -
2214 //but execution was set to 'on hold' as first the TechProfile config had to be applied
Himani Chawla26e555c2020-08-31 12:30:20 +05302215 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
mpagenkodff5dda2020-08-28 11:52:01 +00002216 //VlanFilterFsm exists and was already started (assumed to wait for TechProfile execution here)
2217 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
2218 if pVlanFilterStatemachine != nil {
2219 if pVlanFilterStatemachine.Is(vlanStWaitingTechProf) {
2220 if err := pVlanFilterStatemachine.Event(vlanEvContinueConfig); err != nil {
2221 logger.Warnw("UniVlanConfigFsm: can't continue processing", log.Fields{"err": err})
2222 } else {
2223 /***** UniVlanConfigFsm continued */
2224 logger.Debugw("UniVlanConfigFsm continued", log.Fields{
2225 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
2226 "UniPort": apUniPort.portNo})
2227 }
2228 } else {
2229 logger.Debugw("no state of UniVlanConfigFsm to be continued", log.Fields{
2230 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
2231 }
2232 } else {
2233 logger.Debugw("UniVlanConfigFsm StateMachine does not exist, no flow processing", log.Fields{
2234 "device-id": dh.deviceID})
2235 }
2236
2237 } // else: nothing to do
2238}
2239
2240//RemoveVlanFilterFsm deletes the stored pointer to the VlanConfigFsm
2241// 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 +05302242func (dh *deviceHandler) RemoveVlanFilterFsm(apUniPort *onuUniPort) {
mpagenkodff5dda2020-08-28 11:52:01 +00002243 logger.Debugw("remove UniVlanConfigFsm StateMachine", log.Fields{
2244 "device-id": dh.deviceID, "uniPort": apUniPort.portNo})
2245 //save to do, even if entry dows not exist
Himani Chawla26e555c2020-08-31 12:30:20 +05302246 delete(dh.UniVlanConfigFsmMap, apUniPort.uniID)
mpagenkodff5dda2020-08-28 11:52:01 +00002247}
Holger Hildebrandt47555e72020-09-21 11:07:24 +00002248
2249//storePersUniFlowConfig updates local storage of OnuUniFlowConfig and writes it into kv-store afterwards to have it
2250//available for potential reconcilement
2251
2252func (dh *deviceHandler) storePersUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]uniVlanFlowParams) error {
2253
2254 if dh.reconciling {
2255 logger.Debugw("reconciling - don't store persistent UniFlowConfig", log.Fields{"device-id": dh.deviceID})
2256 return nil
2257 }
2258 logger.Debugw("Store persistent UniFlowConfig", log.Fields{"device-id": dh.deviceID})
2259
2260 pDevEntry := dh.getOnuDeviceEntry(true)
2261 if pDevEntry == nil {
2262 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
2263 return fmt.Errorf("no valid OnuDevice: %s", dh.deviceID)
2264 }
2265 pDevEntry.updateOnuUniFlowConfig(aUniID, aUniVlanFlowParams)
2266
2267 pDevEntry.lockOnuKVStoreMutex()
2268 defer pDevEntry.unlockOnuKVStoreMutex()
2269
2270 // deadline context to ensure completion of background routines waited for
2271 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
Himani Chawlad96df182020-09-28 11:12:02 +05302272 deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
Holger Hildebrandt47555e72020-09-21 11:07:24 +00002273 dctx, cancel := context.WithDeadline(context.Background(), deadline)
2274
2275 pDevEntry.resetKvProcessingErrorIndication()
2276 var wg sync.WaitGroup
2277 wg.Add(1) // for the 1 go routine to finish
2278
2279 go pDevEntry.updateOnuKvStore(dctx, &wg)
mpagenko01e726e2020-10-23 09:45:29 +00002280 dh.waitForCompletion(cancel, &wg, "UpdateKvStore") //wait for background process to finish
Holger Hildebrandt47555e72020-09-21 11:07:24 +00002281
2282 return pDevEntry.getKvProcessingErrorIndication()
2283}
2284
mpagenko01e726e2020-10-23 09:45:29 +00002285func (dh *deviceHandler) waitForCompletion(cancel context.CancelFunc, wg *sync.WaitGroup, aCallerIdent string) {
Holger Hildebrandt47555e72020-09-21 11:07:24 +00002286 defer cancel() //ensure termination of context (may be pro forma)
2287 wg.Wait()
mpagenko01e726e2020-10-23 09:45:29 +00002288 logger.Debugw("WaitGroup processing completed", log.Fields{
2289 "device-id": dh.deviceID, "called from": aCallerIdent})
Holger Hildebrandt47555e72020-09-21 11:07:24 +00002290}
2291
2292func (dh *deviceHandler) combineErrorStrings(errS ...error) error {
2293 var errStr string = ""
2294 for _, err := range errS {
2295 if err != nil {
2296 errStr = errStr + err.Error() + " "
2297 }
2298 }
2299 if errStr != "" {
2300 return fmt.Errorf("%s: %s", errStr, dh.deviceID)
2301 }
2302 return nil
2303}