blob: 395b369e94072db9a1999b6ae91e3581a9499364 [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 (
73 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
84)
85
86const (
87 cEventObjectType = "ONU"
88)
89const (
90 cOnuActivatedEvent = "ONU_ACTIVATED"
91)
92
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000093//DeviceHandler will interact with the ONU ? device.
94type DeviceHandler struct {
95 deviceID string
96 DeviceType string
97 adminState string
98 device *voltha.Device
99 logicalDeviceID string
100 ProxyAddressID string
101 ProxyAddressType string
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000102 parentId string
103 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
111 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
mpagenkoaf801632020-07-03 10:00:42 +0000114 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
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000119 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
133 uniEntityMap map[uint32]*OnuUniPort
134 UniVlanConfigFsmMap map[uint8]*UniVlanConfigFsm
135 reconciling bool
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000136}
137
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000138//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
141 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.
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000158 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
187// 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
194// stop stops the device dh. Not much to do for now
195func (dh *DeviceHandler) stop(ctx context.Context) {
196 logger.Debug("stopping-device-handler")
197 dh.exitChannel <- 1
198}
199
200// ##########################################################################################
201// DeviceHandler methods that implement the adapters interface requests ##### begin #########
202
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000203//AdoptOrReconcileDevice adopts the OLT device
204func (dh *DeviceHandler) AdoptOrReconcileDevice(ctx context.Context, device *voltha.Device) {
205 logger.Debugw("Adopt_or_reconcile_device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000206
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000207 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
mpagenko1cc3cb42020-07-27 15:24:38 +0000208 if dh.pDeviceStateFsm.Is(devStNull) {
209 if err := dh.pDeviceStateFsm.Event(devEvDeviceInit); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000210 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
211 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000212 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000213 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000214 logger.Debugw("AdoptOrReconcileDevice: Agent/device init already done", log.Fields{"device-id": device.Id})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000215 }
216
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000217}
218
219//ProcessInterAdapterMessage sends the proxied messages to the target device
220// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
221// is meant, and then send the unmarshalled omci message to this onu
222func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
223 msgID := msg.Header.Id
224 msgType := msg.Header.Type
225 fromTopic := msg.Header.FromTopic
226 toTopic := msg.Header.ToTopic
227 toDeviceID := msg.Header.ToDeviceId
228 proxyDeviceID := msg.Header.ProxyDeviceId
229 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
230 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
231
232 switch msgType {
233 case ic.InterAdapterMessageType_OMCI_REQUEST:
234 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000235 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000236 omciMsg := &ic.InterAdapterOmciMessage{}
237 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000238 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000239 "device-id": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000240 return err
241 }
242
243 //assuming omci message content is hex coded!
244 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000245 logger.Debugw("inter-adapter-recv-omci", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000246 "device-id": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000247 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000248 pDevEntry := dh.GetOnuDeviceEntry(true)
249 if pDevEntry != nil {
250 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
251 } else {
divyadesai4d299552020-08-18 07:13:49 +0000252 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000253 return errors.New("No valid OnuDevice")
254 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000255 }
256 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
257 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000258 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000259 onu_indication := &oop.OnuIndication{}
260 if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000261 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000262 "device-id": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000263 return err
264 }
265
266 onu_operstate := onu_indication.GetOperState()
267 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onu_indication.GetOnuId(),
268 "AdminState": onu_indication.GetAdminState(), "OperState": onu_operstate,
269 "SNR": onu_indication.GetSerialNumber()})
270
mpagenko3af1f032020-06-10 08:53:41 +0000271 //interface related functions might be error checked ....
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000272 if onu_operstate == "up" {
273 dh.create_interface(onu_indication)
274 } else if (onu_operstate == "down") || (onu_operstate == "unreachable") {
mpagenko3af1f032020-06-10 08:53:41 +0000275 dh.updateInterface(onu_indication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000276 } else {
277 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onu_indication.GetOnuId()})
278 return errors.New("InvalidOperState")
279 }
280 }
mpagenkoaf801632020-07-03 10:00:42 +0000281 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
282 {
283 if dh.pOnuTP == nil {
284 //should normally not happen ...
285 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000286 log.Fields{"device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000287 return errors.New("TechProfile DLMsg request while onuTechProf instance not setup")
288 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000289 if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
290 // I've seen cases for this request, where the device was already stopped
divyadesai4d299552020-08-18 07:13:49 +0000291 logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000292 return errors.New("device-unreachable")
293 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000294
mpagenkoaf801632020-07-03 10:00:42 +0000295 msgBody := msg.GetBody()
296 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
297 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
298 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000299 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000300 return err
301 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000302
mpagenkoaf801632020-07-03 10:00:42 +0000303 // we have to lock access to TechProfile processing based on different messageType calls or
304 // even to fast subsequent calls of the same messageType
305 dh.pOnuTP.lockTpProcMutex()
306 // lock hangs as long as below decoupled or other related TechProfile processing is active
307 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify == true {
308 // if there has been some change for some uni TechProfilePath
309 //in order to allow concurrent calls to other dh instances we do not wait for execution here
310 //but doing so we can not indicate problems to the caller (who does what with that then?)
311 //by now we just assume straightforward successful execution
312 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
313 // possible problems to the caller later autonomously
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000314
mpagenko3dbcdd22020-07-22 07:38:45 +0000315 // deadline context to ensure completion of background routines waited for
316 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
317 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
318 dctx, cancel := context.WithDeadline(context.Background(), deadline)
319
mpagenko1cc3cb42020-07-27 15:24:38 +0000320 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000321 var wg sync.WaitGroup
322 wg.Add(2) // for the 2 go routines to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000323 // attention: deadline completion check and wg.Done is to be done in both routines
mpagenkodff5dda2020-08-28 11:52:01 +0000324 go dh.pOnuTP.configureUniTp(dctx, uint8(techProfMsg.UniId), techProfMsg.Path, &wg)
mpagenko3dbcdd22020-07-22 07:38:45 +0000325 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000326 //the wait.. function is responsible for tpProcMutex.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000327 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
mpagenko1cc3cb42020-07-27 15:24:38 +0000328 return err
mpagenkoaf801632020-07-03 10:00:42 +0000329 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000330 // no change, nothing really to do
331 dh.pOnuTP.unlockTpProcMutex()
332 //return success
333 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000334 }
335 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
336 {
337 if dh.pOnuTP == nil {
338 //should normally not happen ...
339 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000340 log.Fields{"device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000341 return errors.New("TechProfile DelGem request while onuTechProf instance not setup")
342 }
343
344 msgBody := msg.GetBody()
345 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
346 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
347 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000348 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000349 return err
350 }
351
352 //compare TECH_PROFILE_DOWNLOAD_REQUEST
353 dh.pOnuTP.lockTpProcMutex()
mpagenko3dbcdd22020-07-22 07:38:45 +0000354
355 // deadline context to ensure completion of background routines waited for
356 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
357 dctx, cancel := context.WithDeadline(context.Background(), deadline)
358
mpagenko1cc3cb42020-07-27 15:24:38 +0000359 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000360 var wg sync.WaitGroup
361 wg.Add(1) // for the 1 go routine to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000362 go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000363 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
364 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000365 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
366 return err
mpagenkoaf801632020-07-03 10:00:42 +0000367 }
368 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
369 {
370 if dh.pOnuTP == nil {
371 //should normally not happen ...
372 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000373 log.Fields{"device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000374 return errors.New("TechProfile DelTcont request while onuTechProf instance not setup")
375 }
376
377 msgBody := msg.GetBody()
378 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
379 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
380 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000381 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000382 return err
383 }
384
385 //compare TECH_PROFILE_DOWNLOAD_REQUEST
386 dh.pOnuTP.lockTpProcMutex()
387 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify == true {
mpagenko3dbcdd22020-07-22 07:38:45 +0000388 // deadline context to ensure completion of background routines waited for
389 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
390 dctx, cancel := context.WithDeadline(context.Background(), deadline)
391
mpagenko1cc3cb42020-07-27 15:24:38 +0000392 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000393 var wg sync.WaitGroup
mpagenko3dbcdd22020-07-22 07:38:45 +0000394 wg.Add(2) // for the 2 go routines to finish
395 go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000396 cResourceTcont, delTcontMsg.AllocId, &wg)
397 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
mpagenko3dbcdd22020-07-22 07:38:45 +0000398 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000399 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000400 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
401 return err
mpagenkoaf801632020-07-03 10:00:42 +0000402 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000403 dh.pOnuTP.unlockTpProcMutex()
404 //return success
405 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000406 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000407 default:
408 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000409 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000410 "device-id": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000411 return errors.New("unimplemented")
412 }
413 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000414 return nil
415}
416
mpagenkodff5dda2020-08-28 11:52:01 +0000417//FlowUpdateIncremental removes and/or adds the flow changes on a given device
418func (dh *DeviceHandler) FlowUpdateIncremental(apOfFlowChanges *openflow_13.FlowChanges,
419 apOfGroupChanges *openflow_13.FlowGroupChanges, apFlowMetaData *voltha.FlowMetadata) error {
420
421 //Remove flows
422 if apOfFlowChanges.ToRemove != nil {
423 for _, flowItem := range apOfFlowChanges.ToRemove.Items {
424 logger.Debugw("incremental flow item remove", log.Fields{"deviceId": dh.deviceID,
425 "Item": flowItem})
426 }
427 }
428 if apOfFlowChanges.ToAdd != nil {
429 for _, flowItem := range apOfFlowChanges.ToAdd.Items {
430 if flowItem.GetCookie() == 0 {
431 logger.Debugw("incremental flow add - no cookie - ignore", log.Fields{
432 "deviceId": dh.deviceID})
433 continue
434 }
435 flowInPort := flow.GetInPort(flowItem)
436 if flowInPort == uint32(of.OfpPortNo_OFPP_INVALID) {
437 logger.Errorw("flow inPort invalid", log.Fields{"deviceID": dh.deviceID})
438 return errors.New("flow inPort invalid")
439 } else if flowInPort == dh.ponPortNumber {
440 //this is some downstream flow
441 logger.Debugw("incremental flow ignore downstream", log.Fields{
442 "deviceId": dh.deviceID, "inPort": flowInPort})
443 continue
444 } else {
445 // this is the relevant upstream flow
446 var loUniPort *OnuUniPort
447 if uniPort, exist := dh.uniEntityMap[flowInPort]; exist {
448 loUniPort = uniPort
449 } else {
450 logger.Errorw("flow inPort not found in UniPorts",
451 log.Fields{"deviceID": dh.deviceID, "inPort": flowInPort})
452 return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
453 }
454 flowOutPort := flow.GetOutPort(flowItem)
455 logger.Debugw("incremental flow-add port indications", log.Fields{
456 "deviceId": dh.deviceID, "inPort": flowInPort, "outPort": flowOutPort,
457 "uniPortName": loUniPort.name})
458 err := dh.addFlowItemToUniPort(flowItem, loUniPort)
459 //abort processing in error case
460 if err != nil {
461 return err
462 }
463 }
464 }
465 }
466 return nil
467}
468
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000469//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000470// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
471// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300472func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000473 logger.Debugw("disable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000474
mpagenko3af1f032020-06-10 08:53:41 +0000475 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
476 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
477 if dh.deviceReason != "omci-admin-lock" {
478 // disable UNI ports/ONU
479 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
480 // here the result of the processing is not checked (trusted in background) *****
481 if dh.pLockStateFsm == nil {
482 dh.createUniLockFsm(true, UniAdminStateDone)
483 } else { //LockStateFSM already init
484 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
485 dh.runUniLockFsm(true)
486 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300487
mpagenko3af1f032020-06-10 08:53:41 +0000488 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000489 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000490 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000491 }
492 dh.deviceReason = "omci-admin-lock"
493 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
494 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
495 voltha.OperStatus_UNKNOWN); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000496 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000497 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000498 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300499 }
500}
501
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000502//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000503// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
504// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300505func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000506 logger.Debugw("reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000507
508 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300509 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
510 voltha.OperStatus_ACTIVE); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000511 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000512 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300513 }
514
mpagenko3af1f032020-06-10 08:53:41 +0000515 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000516 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000517 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000518 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300519 }
mpagenko3af1f032020-06-10 08:53:41 +0000520 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000521
522 // enable ONU/UNI ports
523 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
524 // here the result of the processing is not checked (trusted in background) *****
525 if dh.pUnlockStateFsm == nil {
526 dh.createUniLockFsm(false, UniAdminStateDone)
527 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000528 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000529 dh.runUniLockFsm(false)
530 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300531}
532
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000533func (dh *DeviceHandler) ReconcileDeviceOnuInd() {
534 logger.Debugw("reconciling - simulate onu indication", log.Fields{"device-id": dh.deviceID})
535
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000536 if err := dh.pOnuTP.restoreFromOnuTpPathKvStore(context.TODO()); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000537 logger.Errorw("reconciling - restoring OnuTp-data failed - abort", log.Fields{"err": err, "device-id": dh.deviceID})
538 dh.reconciling = false
539 return
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000540 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000541 var onu_indication oop.OnuIndication
542 onu_indication.IntfId = dh.pOnuTP.sOnuPersistentData.PersIntfID
543 onu_indication.OnuId = dh.pOnuTP.sOnuPersistentData.PersOnuID
544 onu_indication.OperState = dh.pOnuTP.sOnuPersistentData.PersOperState
545 onu_indication.AdminState = dh.pOnuTP.sOnuPersistentData.PersAdminState
546 dh.create_interface(&onu_indication)
547}
548
549func (dh *DeviceHandler) ReconcileDeviceTechProf() {
550 logger.Debugw("reconciling - trigger tech profile config", log.Fields{"device-id": dh.deviceID})
551
552 dh.pOnuTP.lockTpProcMutex()
553 // lock hangs as long as below decoupled or other related TechProfile processing is active
554 for _, uniData := range dh.pOnuTP.sOnuPersistentData.PersUniTpPath {
555 //In order to allow concurrent calls to other dh instances we do not wait for execution here
556 //but doing so we can not indicate problems to the caller (who does what with that then?)
557 //by now we just assume straightforward successful execution
558 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
559 // possible problems to the caller later autonomously
560
561 // deadline context to ensure completion of background routines waited for
562 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
563 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
564 dctx, cancel := context.WithDeadline(context.Background(), deadline)
565
566 dh.pOnuTP.resetProcessingErrorIndication()
567 var wg sync.WaitGroup
568 wg.Add(1) // for the 1 go routines to finish
569 // attention: deadline completion check and wg.Done is to be done in both routines
mpagenkodff5dda2020-08-28 11:52:01 +0000570 go dh.pOnuTP.configureUniTp(dctx, uint8(uniData.PersUniId), uniData.PersTpPath, &wg)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000571 //the wait.. function is responsible for tpProcMutex.Unlock()
572 dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
573 return
574 }
575 dh.pOnuTP.unlockTpProcMutex()
576 //TODO: reset of reconciling-flag has always to be done in the last ReconcileDevice*() function
577 dh.reconciling = false
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000578}
579
580func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000581 logger.Debugw("delete-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000582 if err := dh.pOnuTP.deleteOnuTpPathKvStore(context.TODO()); err != nil {
583 return err
584 }
585 // TODO: further actions - stop metrics and FSMs, remove device ...
586 return nil
587}
588
ozgecanetsiae11479f2020-07-06 09:44:47 +0300589func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000590 logger.Debugw("reboot-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300591 if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
divyadesai4d299552020-08-18 07:13:49 +0000592 logger.Errorw("device-unreachable", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300593 return errors.New("device-unreachable")
594 }
595 dh.pOnuOmciDevice.Reboot(context.TODO())
596 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
597 voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000598 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000599 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300600 return err
601 }
602 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting-onu"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000603 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000604 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300605 return err
606 }
607 dh.deviceReason = "rebooting-onu"
608 return nil
609}
610
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000611// DeviceHandler methods that implement the adapters interface requests## end #########
612// #####################################################################################
613
614// ################ to be updated acc. needs of ONU Device ########################
615// DeviceHandler StateMachine related state transition methods ##### begin #########
616
617func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
618 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})
619}
620
621// doStateInit provides the device update to the core
622func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
623
624 logger.Debug("doStateInit-started")
625 var err error
626
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000627 // populate what we know. rest comes later after mib sync
628 dh.device.Root = false
629 dh.device.Vendor = "OpenONU"
630 dh.device.Model = "go"
631 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000632 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000633
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000634 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000635
636 if !dh.reconciling {
637 dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
638 } else {
639 logger.Debugw("reconciling - don't notify core about DeviceUpdate",
640 log.Fields{"device-id": dh.deviceID})
641 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000642
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000643 dh.parentId = dh.device.ParentId
644 dh.ponPortNumber = dh.device.ParentPortNo
645
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000646 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
647 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
648 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
divyadesai4d299552020-08-18 07:13:49 +0000649 logger.Debugw("device-updated", log.Fields{"device-id": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000650 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000651 "ParentId": dh.parentId, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000652
653 /*
654 self._pon = PonPort.create(self, self._pon_port_number)
655 self._pon.add_peer(self.parent_id, self._pon_port_number)
656 self.logger.debug('adding-pon-port-to-agent',
657 type=self._pon.get_port().type,
658 admin_state=self._pon.get_port().admin_state,
659 oper_status=self._pon.get_port().oper_status,
660 )
661 */
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000662 if !dh.reconciling {
663 logger.Debugw("adding-pon-port", log.Fields{"deviceID": dh.deviceID, "ponPortNo": dh.ponPortNumber})
664 var ponPortNo uint32 = 1
665 if dh.ponPortNumber != 0 {
666 ponPortNo = dh.ponPortNumber
667 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000668
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000669 pPonPort := &voltha.Port{
670 PortNo: ponPortNo,
671 Label: fmt.Sprintf("pon-%d", ponPortNo),
672 Type: voltha.Port_PON_ONU,
673 OperStatus: voltha.OperStatus_ACTIVE,
674 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentId, // Peer device is OLT
675 PortNo: ponPortNo}}, // Peer port is parent's port number
676 }
677 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
678 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
679 e.Cancel(err)
680 return
681 }
682 } else {
683 logger.Debugw("reconciling - pon-port already added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000684 }
685 logger.Debug("doStateInit-done")
686}
687
688// postInit setups the DeviceEntry for the conerned device
689func (dh *DeviceHandler) postInit(e *fsm.Event) {
690
691 logger.Debug("postInit-started")
692 var err error
693 /*
694 dh.Client = oop.NewOpenoltClient(dh.clientCon)
695 dh.pTransitionMap.Handle(ctx, GrpcConnected)
696 return nil
697 */
mpagenko3af1f032020-06-10 08:53:41 +0000698 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
699 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000700 e.Cancel(err)
701 return
702 }
703
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000704 if dh.reconciling {
705 go dh.ReconcileDeviceOnuInd()
706 // reconcilement will be continued after mib download is done
707 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000708 /*
709 ############################################################################
710 # Setup Alarm handler
711 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
712 device.serial_number)
713 ############################################################################
714 # Setup PM configuration for this device
715 # Pass in ONU specific options
716 kwargs = {
717 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
718 'heartbeat': self.heartbeat,
719 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
720 }
721 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
722 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
723 self.logical_device_id, device.serial_number,
724 grouped=True, freq_override=False, **kwargs)
725 pm_config = self._pm_metrics.make_proto()
726 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
727 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
728 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
729
730 # Note, ONU ID and UNI intf set in add_uni_port method
731 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
732 ani_ports=[self._pon])
733
734 # Code to Run OMCI Test Action
735 kwargs_omci_test_action = {
736 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
737 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
738 }
739 serial_number = device.serial_number
740 self._test_request = OmciTestRequest(self.core_proxy,
741 self.omci_agent, self.device_id,
742 AniG, serial_number,
743 self.logical_device_id,
744 exclusive=False,
745 **kwargs_omci_test_action)
746
747 self.enabled = True
748 else:
749 self.logger.info('onu-already-activated')
750 */
751 logger.Debug("postInit-done")
752}
753
754// doStateConnected get the device info and update to voltha core
755// for comparison of the original method (not that easy to uncomment): compare here:
756// voltha-openolt-adapter/adaptercore/device_handler.go
757// -> this one obviously initiates all communication interfaces of the device ...?
758func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
759
760 logger.Debug("doStateConnected-started")
761 var err error
762 err = errors.New("Device FSM: function not implemented yet!")
763 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000764 logger.Debug("doStateConnected-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700765 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000766}
767
768// doStateUp handle the onu up indication and update to voltha core
769func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
770
771 logger.Debug("doStateUp-started")
772 var err error
773 err = errors.New("Device FSM: function not implemented yet!")
774 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000775 logger.Debug("doStateUp-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700776 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000777
778 /*
779 // Synchronous call to update device state - this method is run in its own go routine
780 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
781 voltha.OperStatus_ACTIVE); err != nil {
782 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
783 return err
784 }
785 return nil
786 */
787}
788
789// doStateDown handle the onu down indication
790func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
791
792 logger.Debug("doStateDown-started")
793 var err error
794
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000795 device := dh.device
796 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000797 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000798 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000799 e.Cancel(err)
800 return
801 }
802
803 cloned := proto.Clone(device).(*voltha.Device)
804 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
805 /*
806 // Update the all ports state on that device to disable
807 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
808 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
809 return er
810 }
811
812 //Update the device oper state and connection status
813 cloned.OperStatus = voltha.OperStatus_UNKNOWN
814 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
815 dh.device = cloned
816
817 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
818 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
819 return er
820 }
821
822 //get the child device for the parent device
823 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
824 if err != nil {
825 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
826 return err
827 }
828 for _, onuDevice := range onuDevices.Items {
829
830 // Update onu state as down in onu adapter
831 onuInd := oop.OnuIndication{}
832 onuInd.OperState = "down"
833 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
834 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
835 if er != nil {
836 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
837 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
838 //Do not return here and continue to process other ONUs
839 }
840 }
841 // * Discovered ONUs entries need to be cleared , since after OLT
842 // is up, it starts sending discovery indications again* /
843 dh.discOnus = sync.Map{}
844 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
845 return nil
846 */
847 err = errors.New("Device FSM: function not implemented yet!")
848 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000849 logger.Debug("doStateDown-done")
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700850 return
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000851}
852
853// DeviceHandler StateMachine related state transition methods ##### end #########
854// #################################################################################
855
856// ###################################################
857// DeviceHandler utility methods ##### begin #########
858
mpagenko3af1f032020-06-10 08:53:41 +0000859//GetOnuDeviceEntry getsthe ONU device entry and may wait until its value is defined
860func (dh *DeviceHandler) GetOnuDeviceEntry(aWait bool) *OnuDeviceEntry {
861 dh.lockDevice.RLock()
862 pOnuDeviceEntry := dh.pOnuOmciDevice
863 if aWait && pOnuDeviceEntry == nil {
864 //keep the read sema short to allow for subsequent write
865 dh.lockDevice.RUnlock()
divyadesai4d299552020-08-18 07:13:49 +0000866 logger.Debugw("Waiting for DeviceEntry to be set ...", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000867 // based on concurrent processing the deviceEntry setup may not yet be finished at his point
868 // so it might be needed to wait here for that event with some timeout
869 select {
870 case <-time.After(60 * time.Second): //timer may be discussed ...
divyadesai4d299552020-08-18 07:13:49 +0000871 logger.Errorw("No valid DeviceEntry set after maxTime", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000872 return nil
873 case <-dh.deviceEntrySet:
divyadesai4d299552020-08-18 07:13:49 +0000874 logger.Debugw("devicEntry ready now - continue", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000875 // if written now, we can return the written value without sema
876 return dh.pOnuOmciDevice
877 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000878 }
mpagenko3af1f032020-06-10 08:53:41 +0000879 dh.lockDevice.RUnlock()
880 return pOnuDeviceEntry
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000881}
882
mpagenko3af1f032020-06-10 08:53:41 +0000883//SetOnuDeviceEntry sets the ONU device entry within the handler
mpagenkoaf801632020-07-03 10:00:42 +0000884func (dh *DeviceHandler) SetOnuDeviceEntry(
885 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000886 dh.lockDevice.Lock()
887 defer dh.lockDevice.Unlock()
mpagenkoaf801632020-07-03 10:00:42 +0000888 dh.pOnuOmciDevice = apDeviceEntry
889 dh.pOnuTP = apOnuTp
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000890 return nil
891}
892
mpagenko3af1f032020-06-10 08:53:41 +0000893//AddOnuDeviceEntry creates a new ONU device or returns the existing
894func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
divyadesai4d299552020-08-18 07:13:49 +0000895 logger.Debugw("adding-deviceEntry", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000896
mpagenko3af1f032020-06-10 08:53:41 +0000897 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000898 if deviceEntry == nil {
899 /* costum_me_map in python code seems always to be None,
900 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
901 /* also no 'clock' argument - usage open ...*/
902 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000903 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
904 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000905 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000906 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000907 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000908 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000909 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000910 // fire deviceEntry ready event to spread to possibly waiting processing
911 dh.deviceEntrySet <- true
divyadesai4d299552020-08-18 07:13:49 +0000912 logger.Infow("onuDeviceEntry-added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000913 } else {
divyadesai4d299552020-08-18 07:13:49 +0000914 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000915 }
916 // might be updated with some error handling !!!
917 return nil
918}
919
920// doStateInit provides the device update to the core
921func (dh *DeviceHandler) create_interface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000922 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
923 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
924
925 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000926
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000927 if !dh.reconciling {
928 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
929 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
930 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
931 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
932 }
933 } else {
934 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVATING",
935 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000936 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000937 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
938 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
939 // 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 +0000940 // 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 +0000941 // so let's just try to keep it simple ...
942 /*
943 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
944 if err != nil || device == nil {
945 //TODO: needs to handle error scenarios
946 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
947 return errors.New("Voltha Device not found")
948 }
949 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000950
mpagenko3af1f032020-06-10 08:53:41 +0000951 pDevEntry := dh.GetOnuDeviceEntry(true)
952 if pDevEntry != nil {
953 pDevEntry.Start(context.TODO())
954 } else {
divyadesai4d299552020-08-18 07:13:49 +0000955 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +0000956 return errors.New("No valid OnuDevice")
957 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000958 if !dh.reconciling {
959 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
960 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
961 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"device-id": dh.deviceID, "error": err})
962 }
963 } else {
964 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to starting-openomci",
965 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000966 }
mpagenko3af1f032020-06-10 08:53:41 +0000967 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000968
969 /* this might be a good time for Omci Verify message? */
970 verifyExec := make(chan bool)
971 omci_verify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000972 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000973 true, true) //eclusive and allowFailure (anyway not yet checked)
974 omci_verify.PerformOmciTest(context.TODO(), verifyExec)
975
976 /* give the handler some time here to wait for the OMCi verification result
977 after Timeout start and try MibUpload FSM anyway
978 (to prevent stopping on just not supported OMCI verification from ONU) */
979 select {
980 case <-time.After(2 * time.Second):
981 logger.Warn("omci start-verification timed out (continue normal)")
982 case testresult := <-verifyExec:
983 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
984 }
985
986 /* In py code it looks earlier (on activate ..)
987 # Code to Run OMCI Test Action
988 kwargs_omci_test_action = {
989 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
990 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
991 }
992 serial_number = device.serial_number
993 self._test_request = OmciTestRequest(self.core_proxy,
994 self.omci_agent, self.device_id,
995 AniG, serial_number,
996 self.logical_device_id,
997 exclusive=False,
998 **kwargs_omci_test_action)
999 ...
1000 # Start test requests after a brief pause
1001 if not self._test_request_started:
1002 self._test_request_started = True
1003 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
1004 reactor.callLater(tststart, self._test_request.start_collector)
1005
1006 */
1007 /* which is then: in omci_test_request.py : */
1008 /*
1009 def start_collector(self, callback=None):
1010 """
1011 Start the collection loop for an adapter if the frequency > 0
1012
1013 :param callback: (callable) Function to call to collect PM data
1014 """
1015 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
1016 if callback is None:
1017 callback = self.perform_test_omci
1018
1019 if self.lc is None:
1020 self.lc = LoopingCall(callback)
1021
1022 if self.default_freq > 0:
1023 self.lc.start(interval=self.default_freq / 10)
1024
1025 def perform_test_omci(self):
1026 """
1027 Perform the initial test request
1028 """
1029 ani_g_entities = self._device.configuration.ani_g_entities
1030 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
1031 is not None else None
1032 self._entity_id = ani_g_entities_ids[0]
1033 self.logger.info('perform-test', entity_class=self._entity_class,
1034 entity_id=self._entity_id)
1035 try:
1036 frame = MEFrame(self._entity_class, self._entity_id, []).test()
1037 result = yield self._device.omci_cc.send(frame)
1038 if not result.fields['omci_message'].fields['success_code']:
1039 self.logger.info('Self-Test Submitted Successfully',
1040 code=result.fields[
1041 'omci_message'].fields['success_code'])
1042 else:
1043 raise TestFailure('Test Failure: {}'.format(
1044 result.fields['omci_message'].fields['success_code']))
1045 except TimeoutError as e:
1046 self.deferred.errback(failure.Failure(e))
1047
1048 except Exception as e:
1049 self.logger.exception('perform-test-Error', e=e,
1050 class_id=self._entity_class,
1051 entity_id=self._entity_id)
1052 self.deferred.errback(failure.Failure(e))
1053
1054 */
1055
1056 // PM related heartbeat??? !!!TODO....
1057 //self._heartbeat.enabled = True
1058
mpagenko1cc3cb42020-07-27 15:24:38 +00001059 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
1060 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
1061 * as further OltAdapter processing may rely on the deviceReason event 'MibUploadDone' as a result of the FSM processing
1062 * otherwise some processing synchronisation would be required - cmp. e.g TechProfile processing
1063 */
1064 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +00001065 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001066 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001067 if pMibUlFsm.Is(ulStDisabled) {
1068 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001069 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
1070 return errors.New("Can't go to state starting")
1071 } else {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001072 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001073 //Determine ONU status and start/re-start MIB Synchronization tasks
1074 //Determine if this ONU has ever synchronized
1075 if true { //TODO: insert valid check
mpagenko1cc3cb42020-07-27 15:24:38 +00001076 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001077 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
1078 return errors.New("Can't go to state resetting_mib")
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001079 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001080 } else {
mpagenko1cc3cb42020-07-27 15:24:38 +00001081 pMibUlFsm.Event(ulEvExamineMds)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001082 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001083 //Examine the MIB Data Sync
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001084 // callbacks to be handled:
mpagenko1cc3cb42020-07-27 15:24:38 +00001085 // Event(ulEvSuccess)
1086 // Event(ulEvTimeout)
1087 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001088 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001089 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001090 } else {
1091 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
1092 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001093 }
1094 } else {
divyadesai4d299552020-08-18 07:13:49 +00001095 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001096 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001097 }
1098 return nil
1099}
1100
mpagenko3af1f032020-06-10 08:53:41 +00001101func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
1102 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
1103 if dh.deviceReason != "stopping-openomci" {
divyadesai4d299552020-08-18 07:13:49 +00001104 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001105 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
1106 pDevEntry := dh.GetOnuDeviceEntry(false)
1107 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001108 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001109 return errors.New("No valid OnuDevice")
1110 }
1111
1112 switch dh.deviceReason {
1113 case "starting-openomci":
1114 { //MIBSync FSM may run
1115 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
1116 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001117 pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +00001118 }
1119 }
1120 case "discovery-mibsync-complete":
1121 { //MibDownload may run
1122 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1123 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001124 pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001125 }
1126 }
1127 default:
mpagenko3dbcdd22020-07-22 07:38:45 +00001128 {
1129 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +00001130 if dh.pUnlockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001131 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001132 }
1133 if dh.pLockStateFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001134 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001135 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001136 //techProfile related PonAniConfigFsm FSM may be active
1137 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
1138 if dh.pOnuTP.pAniConfigFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001139 dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +00001140 }
mpagenkodff5dda2020-08-28 11:52:01 +00001141 for _, uniPort := range dh.uniEntityMap {
1142 //reset the TechProfileConfig Done state for all (active) UNI's
1143 dh.pOnuTP.setConfigDone(uniPort.uniId, false)
1144 // reset tjhe possibly existing VlanConfigFsm
1145 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[uniPort.uniId]; exist {
1146 //VlanFilterFsm exists and was already started
1147 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1148 if pVlanFilterStatemachine != nil {
1149 pVlanFilterStatemachine.Event(vlanEvReset)
1150 }
1151 }
1152 }
mpagenko3af1f032020-06-10 08:53:41 +00001153 }
1154 //TODO!!! care about PM/Alarm processing once started
1155 }
1156 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
1157 // (mainly the still seperate 'Event states')
1158 // so it is questionable, how this is resolved after some possible re-enable
1159 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1160
1161 //stop/remove(?) the device entry
1162 pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
1163
1164 //TODO!!! remove existing traffic profiles
1165 /* from py code, if TP's exist, remove them - not yet implemented
1166 self._tp = dict()
1167 # Let TP download happen again
1168 for uni_id in self._tp_service_specific_task:
1169 self._tp_service_specific_task[uni_id].clear()
1170 for uni_id in self._tech_profile_download_done:
1171 self._tech_profile_download_done[uni_id].clear()
1172 */
1173
1174 dh.disableUniPortStateUpdate()
1175
1176 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001177 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001178 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
divyadesai4d299552020-08-18 07:13:49 +00001179 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001180 // abort: system behavior is just unstable ...
1181 return err
1182 }
1183 dh.deviceReason = "stopping-openomci"
1184
1185 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1186 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001187 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001188 logger.Errorw("error-updating-device-state unreachable-discovered",
divyadesai4d299552020-08-18 07:13:49 +00001189 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001190 // abort: system behavior is just unstable ...
1191 return err
1192 }
1193 } else {
divyadesai4d299552020-08-18 07:13:49 +00001194 logger.Debugw("updateInterface - device already stopped", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001195 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001196 return nil
1197}
1198
mpagenko3af1f032020-06-10 08:53:41 +00001199//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001200func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
1201 switch dev_Event {
1202 case MibDatabaseSync:
1203 {
divyadesai4d299552020-08-18 07:13:49 +00001204 logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001205 if !dh.reconciling {
1206 //initiate DevStateUpdate
1207 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1208 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1209 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1210 "device-id": dh.deviceID, "error": err})
1211 } else {
1212 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
1213 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001214 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001215 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
1216 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001217 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001218 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001219 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001220
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001221 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001222 pDevEntry := dh.GetOnuDeviceEntry(false)
1223 if unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001224 for _, mgmtEntityId := range unigInstKeys {
1225 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001226 "device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001227 dh.addUniPort(mgmtEntityId, i, UniPPTP)
1228 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001229 }
1230 } else {
divyadesai4d299552020-08-18 07:13:49 +00001231 logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001232 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001233 if veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001234 for _, mgmtEntityId := range veipInstKeys {
1235 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001236 "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityId})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001237 dh.addUniPort(mgmtEntityId, i, UniVEIP)
1238 i++
1239 }
1240 } else {
divyadesai4d299552020-08-18 07:13:49 +00001241 logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001242 }
1243 if i == 0 {
divyadesai4d299552020-08-18 07:13:49 +00001244 logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001245 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001246
mpagenko3af1f032020-06-10 08:53:41 +00001247 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1248 * left the code here as comment in case such processing should prove needed unexpectedly
1249 // Init Uni Ports to Admin locked state
1250 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1251 // *** should generate UniLockStateDone event *****
1252 if dh.pLockStateFsm == nil {
1253 dh.createUniLockFsm(true, UniLockStateDone)
1254 } else { //LockStateFSM already init
1255 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1256 dh.runUniLockFsm(true)
1257 }
1258 }
1259 case UniLockStateDone:
1260 {
divyadesai4d299552020-08-18 07:13:49 +00001261 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001262 * lockState processing commented out
1263 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001264 /* Mib download procedure -
1265 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1266 */
mpagenko3af1f032020-06-10 08:53:41 +00001267 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001268 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001269 if pMibDlFsm.Is(dlStDisabled) {
1270 if err := pMibDlFsm.Event(dlEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001271 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1272 // maybe try a FSM reset and then again ... - TODO!!!
1273 } else {
1274 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1275 // maybe use more specific states here for the specific download steps ...
mpagenko1cc3cb42020-07-27 15:24:38 +00001276 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001277 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1278 } else {
1279 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1280 //Begin MIB data download (running autonomously)
1281 }
1282 }
1283 } else {
1284 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1285 // maybe try a FSM reset and then again ... - TODO!!!
1286 }
1287 /***** Mib download started */
1288 } else {
divyadesai4d299552020-08-18 07:13:49 +00001289 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001290 }
1291 }
1292 case MibDownloadDone:
1293 {
divyadesai4d299552020-08-18 07:13:49 +00001294 logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001295 //initiate DevStateUpdate
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001296 if !dh.reconciling {
1297 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1298 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1299 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1300 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1301 } else {
1302 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
1303 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001304 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001305 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
1306 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001307 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001308 if !dh.reconciling {
1309 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1310 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1311 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1312 log.Fields{"device-id": dh.deviceID, "error": err})
1313 } else {
1314 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
1315 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001316 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001317 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
1318 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001319 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001320 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001321 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001322 // *** should generate UniUnlockStateDone event *****
1323 if dh.pUnlockStateFsm == nil {
1324 dh.createUniLockFsm(false, UniUnlockStateDone)
1325 } else { //UnlockStateFSM already init
1326 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1327 dh.runUniLockFsm(false)
1328 }
1329 }
1330 case UniUnlockStateDone:
1331 {
mpagenko3af1f032020-06-10 08:53:41 +00001332 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001333
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001334 if !dh.reconciling {
1335 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
1336 raisedTs := time.Now().UnixNano()
1337 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1338 } else {
1339 logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
1340 log.Fields{"device-id": dh.deviceID})
1341 go dh.ReconcileDeviceTechProf()
1342 //TODO: further actions e.g. restore flows, metrics, ...
1343 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001344 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001345 case OmciAniConfigDone:
1346 {
divyadesai4d299552020-08-18 07:13:49 +00001347 logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001348 // attention: the device reason update is done based on ONU-UNI-Port related activity
1349 // - which may cause some inconsistency
1350 if dh.deviceReason != "tech-profile-config-download-success" {
1351 // which may be the case from some previous actvity on another UNI Port of the ONU
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001352 if !dh.reconciling {
1353 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1354 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1355 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1356 log.Fields{"device-id": dh.deviceID, "error": err})
1357 } else {
1358 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1359 log.Fields{"device-id": dh.deviceID})
1360 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001361 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001362 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
divyadesai4d299552020-08-18 07:13:49 +00001363 log.Fields{"device-id": dh.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001364 }
1365 //set internal state anyway - as it was done
1366 dh.deviceReason = "tech-profile-config-download-success"
1367 }
1368 }
mpagenkodff5dda2020-08-28 11:52:01 +00001369 case OmciVlanFilterDone:
1370 {
1371 logger.Debugw("OmciVlanFilterDone event received",
1372 log.Fields{"device-id": dh.deviceID})
1373 // attention: the device reason update is done based on ONU-UNI-Port related activity
1374 // - which may cause some inconsistency
1375 // yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
1376
1377 if dh.deviceReason != "omci-flows-pushed" {
1378 // which may be the case from some previous actvity on another UNI Port of the ONU
1379 // or even some previous flow add activity on the same port
1380 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
1381 logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
1382 log.Fields{"device-id": dh.deviceID, "error": err})
1383 } else {
1384 logger.Infow("updated dev reason to ''omci-flows-pushed'",
1385 log.Fields{"device-id": dh.deviceID})
1386 }
1387 //set internal state anyway - as it was done
1388 dh.deviceReason = "omci-flows-pushed"
1389 }
1390 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001391 default:
1392 {
divyadesai4d299552020-08-18 07:13:49 +00001393 logger.Warnw("unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": dev_Event})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001394 }
1395 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001396}
1397
Holger Hildebrandtdd23cc22020-05-19 13:32:18 +00001398func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001399 // parameters are IntfId, OnuId, uniId
1400 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
1401 uint32(a_uniId))
1402 if _, present := dh.uniEntityMap[uniNo]; present {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001403 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": a_uniInstNo})
1404 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001405 //with arguments a_uniId, a_portNo, a_portType
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001406 pUniPort := NewOnuUniPort(a_uniId, uniNo, a_uniInstNo, a_portType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001407 if pUniPort == nil {
1408 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": a_uniInstNo})
1409 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001410 //store UniPort with the System-PortNumber key
1411 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001412 if !dh.reconciling {
1413 // create announce the UniPort to the core as VOLTHA Port object
1414 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1415 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1416 } //error logging already within UniPort method
1417 } else {
1418 logger.Debugw("reconciling - onuUniPort already added", log.Fields{"for PortNo": uniNo, "device-id": dh.deviceID})
1419 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001420 }
1421 }
1422}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001423
mpagenko3af1f032020-06-10 08:53:41 +00001424// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1425func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001426 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
1427 // but towards core only the first port active state is signalled
1428 // with following remark:
1429 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1430 // # load on the core
1431
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001432 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001433
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001434 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001435 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001436 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1437 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1438 uniPort.SetOperState(vc.OperStatus_ACTIVE)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001439 if !dh.reconciling {
1440 //maybe also use getter functions on uniPort - perhaps later ...
1441 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1442 } else {
1443 logger.Debugw("reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
1444 }
mpagenko3af1f032020-06-10 08:53:41 +00001445 }
1446 }
1447}
1448
1449// Disable UniPortState and update core port state accordingly
1450func (dh *DeviceHandler) disableUniPortStateUpdate() {
1451 // compare enableUniPortStateUpdate() above
1452 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1453 for uniNo, uniPort := range dh.uniEntityMap {
1454 // only if this port is validated for operState transfer
1455 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1456 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1457 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1458 //maybe also use getter functions on uniPort - perhaps later ...
1459 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001460 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001461 }
1462}
1463
1464// ONU_Active/Inactive announcement on system KAFKA bus
1465// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
1466func (dh *DeviceHandler) sendOnuOperStateEvent(a_OperState vc.OperStatus_Types, a_deviceID string, raisedTs int64) {
1467 var de voltha.DeviceEvent
1468 eventContext := make(map[string]string)
1469 //Populating event context
1470 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
1471 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentId, dh.parentId)
1472 if err != nil || parentDevice == nil {
1473 logger.Errorw("Failed to fetch parent device for OnuEvent",
1474 log.Fields{"parentId": dh.parentId, "err": err})
1475 }
1476 oltSerialNumber := parentDevice.SerialNumber
1477
1478 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1479 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1480 eventContext["serial-number"] = dh.device.SerialNumber
1481 eventContext["olt_serial_number"] = oltSerialNumber
1482 eventContext["device_id"] = a_deviceID
1483 eventContext["registration_id"] = a_deviceID //py: string(device_id)??
1484 logger.Debugw("prepare ONU_ACTIVATED event",
1485 log.Fields{"DeviceId": a_deviceID, "EventContext": eventContext})
1486
1487 /* Populating device event body */
1488 de.Context = eventContext
1489 de.ResourceId = a_deviceID
1490 if a_OperState == voltha.OperStatus_ACTIVE {
1491 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1492 de.Description = fmt.Sprintf("%s Event - %s - %s",
1493 cEventObjectType, cOnuActivatedEvent, "Raised")
1494 } else {
1495 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1496 de.Description = fmt.Sprintf("%s Event - %s - %s",
1497 cEventObjectType, cOnuActivatedEvent, "Cleared")
1498 }
1499 /* Send event to KAFKA */
1500 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1501 logger.Warnw("could not send ONU_ACTIVATED event",
divyadesai4d299552020-08-18 07:13:49 +00001502 log.Fields{"device-id": a_deviceID, "error": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001503 }
1504 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
divyadesai4d299552020-08-18 07:13:49 +00001505 log.Fields{"device-id": a_deviceID, "with-EventName": de.DeviceEventName})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001506}
1507
mpagenkodff5dda2020-08-28 11:52:01 +00001508// createUniLockFsm initialises and runs the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001509func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1510 chLSFsm := make(chan Message, 2048)
1511 var sFsmName string
1512 if aAdminState == true {
divyadesai4d299552020-08-18 07:13:49 +00001513 logger.Infow("createLockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001514 sFsmName = "LockStateFSM"
1515 } else {
divyadesai4d299552020-08-18 07:13:49 +00001516 logger.Infow("createUnlockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001517 sFsmName = "UnLockStateFSM"
1518 }
mpagenko3af1f032020-06-10 08:53:41 +00001519
1520 pDevEntry := dh.GetOnuDeviceEntry(true)
1521 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001522 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001523 return
1524 }
1525 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001526 sFsmName, dh.deviceID, chLSFsm)
1527 if pLSFsm != nil {
1528 if aAdminState == true {
1529 dh.pLockStateFsm = pLSFsm
1530 } else {
1531 dh.pUnlockStateFsm = pLSFsm
1532 }
1533 dh.runUniLockFsm(aAdminState)
1534 } else {
divyadesai4d299552020-08-18 07:13:49 +00001535 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001536 }
1537}
1538
1539// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1540func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1541 /* Uni Port lock/unlock procedure -
1542 ***** should run via 'adminDone' state and generate the argument requested event *****
1543 */
1544 var pLSStatemachine *fsm.FSM
1545 if aAdminState == true {
1546 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1547 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1548 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001549 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1550 dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001551 }
1552 } else {
1553 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1554 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1555 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001556 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
1557 dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001558 }
1559 }
1560 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001561 if pLSStatemachine.Is(uniStDisabled) {
1562 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001563 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1564 // maybe try a FSM reset and then again ... - TODO!!!
1565 } else {
1566 /***** LockStateFSM started */
1567 logger.Debugw("LockStateFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001568 "state": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001569 }
1570 } else {
1571 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001572 "have": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001573 // maybe try a FSM reset and then again ... - TODO!!!
1574 }
1575 } else {
divyadesai4d299552020-08-18 07:13:49 +00001576 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001577 // maybe try a FSM reset and then again ... - TODO!!!
1578 }
1579}
1580
mpagenkoaf801632020-07-03 10:00:42 +00001581//SetBackend provides a DB backend for the specified path on the existing KV client
1582func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1583 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1584 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
divyadesai4d299552020-08-18 07:13:49 +00001585 "BasePathKvStore": aBasePathKvStore, "device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +00001586 kvbackend := &db.Backend{
1587 Client: dh.pOpenOnuAc.kvClient,
1588 StoreType: dh.pOpenOnuAc.KVStoreType,
1589 /* address config update acc. to [VOL-2736] */
1590 Address: addr,
1591 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1592 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001593
mpagenkoaf801632020-07-03 10:00:42 +00001594 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001595}
mpagenkodff5dda2020-08-28 11:52:01 +00001596
1597//addFlowItemToUniPort parses the actual flow item to add it to the UniPort
1598func (dh *DeviceHandler) addFlowItemToUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *OnuUniPort) error {
1599 var loSetVlan uint16 = uint16(of.OfpVlanId_OFPVID_NONE) //noValidEntry
1600 var loMatchVlan uint16 = uint16(of.OfpVlanId_OFPVID_PRESENT) //reserved VLANID entry
1601 var loAddPcp, loSetPcp uint8
1602 /* the TechProfileId is part of the flow Metadata - compare also comment within
1603 * OLT-Adapter:openolt_flowmgr.go
1604 * Metadata 8 bytes:
1605 * Most Significant 2 Bytes = Inner VLAN
1606 * Next 2 Bytes = Tech Profile ID(TPID)
1607 * Least Significant 4 Bytes = Port ID
1608 * Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1609 * subscriber related flows.
1610 */
1611
1612 metadata := flow.GetMetadataFromWriteMetadataAction(apFlowItem)
1613 if metadata == 0 {
1614 logger.Debugw("FlowAdd invalid metadata - abort",
1615 log.Fields{"device-id": dh.deviceID})
1616 return errors.New("FlowAdd invalid metadata")
1617 }
1618 loTpID := flow.GetTechProfileIDFromWriteMetaData(metadata)
1619 logger.Debugw("FlowAdd TechProfileId", log.Fields{"device-id": dh.deviceID, "TP-Id": loTpID})
1620 for _, field := range flow.GetOfbFields(apFlowItem) {
1621 switch field.Type {
1622 case of.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
1623 {
1624 logger.Debugw("FlowAdd type EthType", log.Fields{"device-id": dh.deviceID,
1625 "EthType": strconv.FormatInt(int64(field.GetEthType()), 16)})
1626 }
1627 case of.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
1628 {
1629 loIPProto := field.GetIpProto()
1630 logger.Debugw("FlowAdd type IpProto", log.Fields{"device-id": dh.deviceID,
1631 "IpProto": strconv.FormatInt(int64(loIPProto), 16)})
1632 if loIPProto == 2 {
1633 // some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
1634 // avoids installing invalid EVTOCD rule
1635 logger.Debugw("FlowAdd type IpProto 2: TT workaround: ignore flow",
1636 log.Fields{"device-id": dh.deviceID,
1637 "IpProto": strconv.FormatInt(int64(loIPProto), 16)})
1638 return nil
1639 }
1640 }
1641 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
1642 {
1643 loMatchVlan = uint16(field.GetVlanVid())
1644 loMatchVlanMask := uint16(field.GetVlanVidMask())
1645 if !(loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) &&
1646 loMatchVlanMask == uint16(of.OfpVlanId_OFPVID_PRESENT)) {
1647 loMatchVlan = loMatchVlan & 0xFFF // not transparent: copy only ID bits
1648 }
1649 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1650 "VID": strconv.FormatInt(int64(loMatchVlan), 16)})
1651 }
1652 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
1653 {
1654 loAddPcp = uint8(field.GetVlanPcp())
1655 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1656 "PCP": loAddPcp})
1657 }
1658 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
1659 {
1660 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1661 "UDP-DST": strconv.FormatInt(int64(field.GetUdpDst()), 16)})
1662 }
1663 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
1664 {
1665 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1666 "UDP-SRC": strconv.FormatInt(int64(field.GetUdpSrc()), 16)})
1667 }
1668 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
1669 {
1670 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1671 "IPv4-DST": field.GetIpv4Dst()})
1672 }
1673 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC:
1674 {
1675 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1676 "IPv4-SRC": field.GetIpv4Src()})
1677 }
1678 case of.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
1679 {
1680 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1681 "Metadata": field.GetTableMetadata()})
1682 }
1683 /*
1684 default:
1685 {
1686 //all other entires ignored
1687 }
1688 */
1689 }
1690 } //for all OfbFields
1691
1692 for _, action := range flow.GetActions(apFlowItem) {
1693 switch action.Type {
1694 /* not used:
1695 case of.OfpActionType_OFPAT_OUTPUT:
1696 {
1697 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1698 "Output": action.GetOutput()})
1699 }
1700 */
1701 case of.OfpActionType_OFPAT_PUSH_VLAN:
1702 {
1703 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1704 "PushEthType": strconv.FormatInt(int64(action.GetPush().Ethertype), 16)})
1705 }
1706 case of.OfpActionType_OFPAT_SET_FIELD:
1707 {
1708 pActionSetField := action.GetSetField()
1709 if pActionSetField.Field.OxmClass != of.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1710 logger.Warnw("FlowAdd action SetField invalid OxmClass (ignored)", log.Fields{"device-id": dh.deviceID,
1711 "OxcmClass": pActionSetField.Field.OxmClass})
1712 }
1713 if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1714 loSetVlan = uint16(pActionSetField.Field.GetOfbField().GetVlanVid())
1715 logger.Debugw("FlowAdd Set VLAN from SetField action", log.Fields{"device-id": dh.deviceID,
1716 "SetVlan": strconv.FormatInt(int64(loSetVlan), 16)})
1717 } else if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
1718 loSetPcp = uint8(pActionSetField.Field.GetOfbField().GetVlanPcp())
1719 logger.Debugw("FlowAdd Set PCP from SetField action", log.Fields{"device-id": dh.deviceID,
1720 "SetPcp": loSetPcp})
1721 } else {
1722 logger.Warnw("FlowAdd action SetField invalid FieldType", log.Fields{"device-id": dh.deviceID,
1723 "Type": pActionSetField.Field.GetOfbField().Type})
1724 }
1725 }
1726 /*
1727 default:
1728 {
1729 //all other entires ignored
1730 }
1731 */
1732 }
1733 } //for all Actions
1734
1735 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1736 logger.Errorw("FlowAdd aborted - SetVlanId undefined, but MatchVid set", log.Fields{
1737 "device-id": dh.deviceID, "UniPort": apUniPort.portNo,
1738 "set_vid": strconv.FormatInt(int64(loSetVlan), 16),
1739 "match_vid": strconv.FormatInt(int64(loMatchVlan), 16)})
1740 //TODO!!: Use DeviceId within the error response to rwCore
1741 // likewise also in other error response cases to calling components as requested in [VOL-3458]
1742 return errors.New("FlowAdd Set/Match VlanId inconsistent")
1743 }
1744 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) {
1745 logger.Debugw("FlowAdd vlan-any/copy", log.Fields{"device-id": dh.deviceID})
1746 loSetVlan = loMatchVlan //both 'transparent' (copy any)
1747 } else {
1748 //looks like OMCI value 4097 (copyFromOuter - for Uni double tagged) is not supported here
1749 if loSetVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1750 // not set to transparent
1751 loSetVlan &= 0x0FFF //mask VID bits as prerequiste for vlanConfigFsm
1752 }
1753 logger.Debugw("FlowAdd vlan-set", log.Fields{"device-id": dh.deviceID})
1754 }
1755 //TODO!!: further FlowAdd requests may be valid even in case the FSM is already running,
1756 // e.g. for multi-step flow configuration, error treatment must be redefined in this context as requested in [VOL-3441]
1757 if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniId]; exist {
1758 logger.Errorw("FlowAdd aborted - FSM already running", log.Fields{
1759 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
1760 return errors.New("FlowAdd FSM already running")
1761 }
1762 return dh.createVlanFilterFsm(apUniPort,
1763 loTpID, loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterDone)
1764}
1765
1766// createVlanFilterFsm initialises and runs the VlanFilter FSM to transfer OMCI related VLAN config
1767func (dh *DeviceHandler) createVlanFilterFsm(apUniPort *OnuUniPort,
1768 aTpID uint16, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8, aDevEvent OnuDeviceEvent) error {
1769 chVlanFilterFsm := make(chan Message, 2048)
1770
1771 pDevEntry := dh.GetOnuDeviceEntry(true)
1772 if pDevEntry == nil {
1773 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
1774 return fmt.Errorf("No valid OnuDevice for device-id %x - aborting", dh.deviceID)
1775 }
1776
1777 pVlanFilterFsm := NewUniVlanConfigFsm(dh, pDevEntry.PDevOmciCC, apUniPort, dh.pOnuTP,
1778 pDevEntry.pOnuDB, aTpID, aDevEvent, "UniVlanConfigFsm", dh.deviceID, chVlanFilterFsm,
1779 dh.pOpenOnuAc.AcceptIncrementalEvto, aMatchVlan, aSetVlan, aSetPcp)
1780 if pVlanFilterFsm != nil {
1781 dh.UniVlanConfigFsmMap[apUniPort.uniId] = pVlanFilterFsm
1782 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1783 if pVlanFilterStatemachine != nil {
1784 if pVlanFilterStatemachine.Is(vlanStDisabled) {
1785 if err := pVlanFilterStatemachine.Event(vlanEvStart); err != nil {
1786 logger.Warnw("UniVlanConfigFsm: can't start", log.Fields{"err": err})
1787 return fmt.Errorf("Can't start UniVlanConfigFsm for device-id %x", dh.deviceID)
1788 } else {
1789 /***** UniVlanConfigFsm started */
1790 logger.Debugw("UniVlanConfigFsm started", log.Fields{
1791 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
1792 "UniPort": apUniPort.portNo})
1793 }
1794 } else {
1795 logger.Warnw("wrong state of UniVlanConfigFsm - want: disabled", log.Fields{
1796 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
1797 return fmt.Errorf("UniVlanConfigFsm not in expected disabled state for device-id %x", dh.deviceID)
1798 }
1799 } else {
1800 logger.Errorw("UniVlanConfigFsm StateMachine invalid - cannot be executed!!", log.Fields{
1801 "device-id": dh.deviceID})
1802 return fmt.Errorf("UniVlanConfigFsm invalid for device-id %x", dh.deviceID)
1803 }
1804 } else {
1805 logger.Errorw("UniVlanConfigFsm could not be created - abort!!", log.Fields{
1806 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
1807 return fmt.Errorf("UniVlanConfigFsm could not be created for device-id %x", dh.deviceID)
1808 }
1809 return nil
1810}
1811
1812//verifyUniVlanConfigRequest checks on existence of flow configuration and starts it accordingly
1813func (dh *DeviceHandler) verifyUniVlanConfigRequest(apUniPort *OnuUniPort) {
1814 //TODO!! verify and start pending flow configuration
1815 //some pending config request my exist in case the UniVlanConfig FSM was already started - with internal data -
1816 //but execution was set to 'on hold' as first the TechProfile config had to be applied
1817 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[apUniPort.uniId]; exist {
1818 //VlanFilterFsm exists and was already started (assumed to wait for TechProfile execution here)
1819 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1820 if pVlanFilterStatemachine != nil {
1821 if pVlanFilterStatemachine.Is(vlanStWaitingTechProf) {
1822 if err := pVlanFilterStatemachine.Event(vlanEvContinueConfig); err != nil {
1823 logger.Warnw("UniVlanConfigFsm: can't continue processing", log.Fields{"err": err})
1824 } else {
1825 /***** UniVlanConfigFsm continued */
1826 logger.Debugw("UniVlanConfigFsm continued", log.Fields{
1827 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
1828 "UniPort": apUniPort.portNo})
1829 }
1830 } else {
1831 logger.Debugw("no state of UniVlanConfigFsm to be continued", log.Fields{
1832 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
1833 }
1834 } else {
1835 logger.Debugw("UniVlanConfigFsm StateMachine does not exist, no flow processing", log.Fields{
1836 "device-id": dh.deviceID})
1837 }
1838
1839 } // else: nothing to do
1840}
1841
1842//RemoveVlanFilterFsm deletes the stored pointer to the VlanConfigFsm
1843// intention is to provide this method to be called from VlanConfigFsm itself, when resources (and methods!) are cleaned up
1844func (dh *DeviceHandler) RemoveVlanFilterFsm(apUniPort *OnuUniPort) {
1845 logger.Debugw("remove UniVlanConfigFsm StateMachine", log.Fields{
1846 "device-id": dh.deviceID, "uniPort": apUniPort.portNo})
1847 //save to do, even if entry dows not exist
1848 delete(dh.UniVlanConfigFsmMap, apUniPort.uniId)
1849}