blob: 91b794c55588992d50ee864ea8255cb0f89d765c [file] [log] [blame]
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
22 "encoding/hex"
23 "errors"
24 "fmt"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000025 "strconv"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000026 "sync"
27 "time"
28
29 "github.com/gogo/protobuf/proto"
30 "github.com/golang/protobuf/ptypes"
31 "github.com/looplab/fsm"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +000032 me "github.com/opencord/omci-lib-go/generated"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000033 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
mpagenkoaf801632020-07-03 10:00:42 +000034 "github.com/opencord/voltha-lib-go/v3/pkg/db"
mpagenkodff5dda2020-08-28 11:52:01 +000035 flow "github.com/opencord/voltha-lib-go/v3/pkg/flows"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000036 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Holger Hildebrandt24d51952020-05-04 14:03:42 +000037 vc "github.com/opencord/voltha-protos/v3/go/common"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000038 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
mpagenkodff5dda2020-08-28 11:52:01 +000039 "github.com/opencord/voltha-protos/v3/go/openflow_13"
40 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
41 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000042 oop "github.com/opencord/voltha-protos/v3/go/openolt"
43 "github.com/opencord/voltha-protos/v3/go/voltha"
44)
45
46/*
47// Constants for number of retries and for timeout
48const (
49 MaxRetry = 10
50 MaxTimeOutInMs = 500
51)
52*/
53
mpagenko1cc3cb42020-07-27 15:24:38 +000054const (
55 // events of Device FSM
56 devEvDeviceInit = "devEvDeviceInit"
57 devEvGrpcConnected = "devEvGrpcConnected"
58 devEvGrpcDisconnected = "devEvGrpcDisconnected"
59 devEvDeviceUpInd = "devEvDeviceUpInd"
60 devEvDeviceDownInd = "devEvDeviceDownInd"
61)
62const (
63 // states of Device FSM
64 devStNull = "devStNull"
65 devStDown = "devStDown"
66 devStInit = "devStInit"
67 devStConnected = "devStConnected"
68 devStUp = "devStUp"
69)
70
Holger Hildebrandt24d51952020-05-04 14:03:42 +000071//Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
72const (
Himani Chawla4d908332020-08-31 12:30:20 +053073 pon = voltha.EventSubCategory_PON
74 //olt = voltha.EventSubCategory_OLT
75 //ont = voltha.EventSubCategory_ONT
76 //onu = voltha.EventSubCategory_ONU
77 //nni = voltha.EventSubCategory_NNI
78 //service = voltha.EventCategory_SERVICE
79 //security = voltha.EventCategory_SECURITY
80 equipment = voltha.EventCategory_EQUIPMENT
81 //processing = voltha.EventCategory_PROCESSING
82 //environment = voltha.EventCategory_ENVIRONMENT
83 //communication = voltha.EventCategory_COMMUNICATION
Holger Hildebrandt24d51952020-05-04 14:03:42 +000084)
85
86const (
87 cEventObjectType = "ONU"
88)
89const (
90 cOnuActivatedEvent = "ONU_ACTIVATED"
91)
92
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
Himani Chawla4d908332020-08-31 12:30:20 +0530102 parentID string
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000103 ponPortNumber uint32
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000104
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000105 coreProxy adapterif.CoreProxy
106 AdapterProxy adapterif.AdapterProxy
107 EventProxy adapterif.EventProxy
108
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000109 pOpenOnuAc *OpenONUAC
110 pDeviceStateFsm *fsm.FSM
Himani Chawla4d908332020-08-31 12:30:20 +0530111 //pPonPort *voltha.Port
mpagenko3af1f032020-06-10 08:53:41 +0000112 deviceEntrySet chan bool //channel for DeviceEntry set event
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000113 pOnuOmciDevice *OnuDeviceEntry
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
Himani Chawla4d908332020-08-31 12:30:20 +0530187// Start save the device to the data model
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000188func (dh *DeviceHandler) Start(ctx context.Context) {
divyadesai4d299552020-08-18 07:13:49 +0000189 logger.Debugw("starting-device-handler", log.Fields{"device": dh.device, "device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000190 // Add the initial device to the local model
191 logger.Debug("device-handler-started")
192}
193
Himani Chawla4d908332020-08-31 12:30:20 +0530194/*
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000195// stop stops the device dh. Not much to do for now
196func (dh *DeviceHandler) stop(ctx context.Context) {
197 logger.Debug("stopping-device-handler")
198 dh.exitChannel <- 1
199}
Himani Chawla4d908332020-08-31 12:30:20 +0530200*/
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000201
202// ##########################################################################################
203// DeviceHandler methods that implement the adapters interface requests ##### begin #########
204
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000205//AdoptOrReconcileDevice adopts the OLT device
206func (dh *DeviceHandler) AdoptOrReconcileDevice(ctx context.Context, device *voltha.Device) {
207 logger.Debugw("Adopt_or_reconcile_device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000208
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000209 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
mpagenko1cc3cb42020-07-27 15:24:38 +0000210 if dh.pDeviceStateFsm.Is(devStNull) {
211 if err := dh.pDeviceStateFsm.Event(devEvDeviceInit); err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000212 logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
213 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000214 logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000215 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000216 logger.Debugw("AdoptOrReconcileDevice: Agent/device init already done", log.Fields{"device-id": device.Id})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000217 }
218
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000219}
220
221//ProcessInterAdapterMessage sends the proxied messages to the target device
222// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
223// is meant, and then send the unmarshalled omci message to this onu
224func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
225 msgID := msg.Header.Id
226 msgType := msg.Header.Type
227 fromTopic := msg.Header.FromTopic
228 toTopic := msg.Header.ToTopic
229 toDeviceID := msg.Header.ToDeviceId
230 proxyDeviceID := msg.Header.ProxyDeviceId
231 logger.Debugw("InterAdapter message header", log.Fields{"msgID": msgID, "msgType": msgType,
232 "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
233
234 switch msgType {
235 case ic.InterAdapterMessageType_OMCI_REQUEST:
236 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000237 msgBody := msg.GetBody()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000238 omciMsg := &ic.InterAdapterOmciMessage{}
239 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000240 logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000241 "device-id": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000242 return err
243 }
244
245 //assuming omci message content is hex coded!
246 // with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000247 logger.Debugw("inter-adapter-recv-omci", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000248 "device-id": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000249 //receive_message(omci_msg.message)
mpagenko3af1f032020-06-10 08:53:41 +0000250 pDevEntry := dh.GetOnuDeviceEntry(true)
251 if pDevEntry != nil {
252 return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
mpagenko3af1f032020-06-10 08:53:41 +0000253 }
Himani Chawla4d908332020-08-31 12:30:20 +0530254 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
255 return errors.New("no valid OnuDevice")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000256 }
257 case ic.InterAdapterMessageType_ONU_IND_REQUEST:
258 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000259 msgBody := msg.GetBody()
Himani Chawla4d908332020-08-31 12:30:20 +0530260 onuIndication := &oop.OnuIndication{}
261 if err := ptypes.UnmarshalAny(msgBody, onuIndication); err != nil {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000262 logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000263 "device-id": dh.deviceID, "error": err})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000264 return err
265 }
266
Himani Chawla4d908332020-08-31 12:30:20 +0530267 onuOperstate := onuIndication.GetOperState()
268 logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onuIndication.GetOnuId(),
269 "AdminState": onuIndication.GetAdminState(), "OperState": onuOperstate,
270 "SNR": onuIndication.GetSerialNumber()})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000271
mpagenko3af1f032020-06-10 08:53:41 +0000272 //interface related functions might be error checked ....
Himani Chawla4d908332020-08-31 12:30:20 +0530273 if onuOperstate == "up" {
274 _ = dh.createInterface(onuIndication)
275 } else if (onuOperstate == "down") || (onuOperstate == "unreachable") {
276 _ = dh.updateInterface(onuIndication)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000277 } else {
Himani Chawla4d908332020-08-31 12:30:20 +0530278 logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onuIndication.GetOnuId()})
279 return errors.New("invalidOperState")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000280 }
281 }
mpagenkoaf801632020-07-03 10:00:42 +0000282 case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
283 {
284 if dh.pOnuTP == nil {
285 //should normally not happen ...
286 logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000287 log.Fields{"device-id": dh.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530288 return errors.New("techProfile DLMsg request while onuTechProf instance not setup")
mpagenkoaf801632020-07-03 10:00:42 +0000289 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000290 if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
291 // I've seen cases for this request, where the device was already stopped
divyadesai4d299552020-08-18 07:13:49 +0000292 logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000293 return errors.New("device-unreachable")
294 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000295
mpagenkoaf801632020-07-03 10:00:42 +0000296 msgBody := msg.GetBody()
297 techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
298 if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
299 logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000300 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000301 return err
302 }
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000303
mpagenkoaf801632020-07-03 10:00:42 +0000304 // we have to lock access to TechProfile processing based on different messageType calls or
305 // even to fast subsequent calls of the same messageType
306 dh.pOnuTP.lockTpProcMutex()
307 // lock hangs as long as below decoupled or other related TechProfile processing is active
Himani Chawla4d908332020-08-31 12:30:20 +0530308 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify {
mpagenkoaf801632020-07-03 10:00:42 +0000309 // if there has been some change for some uni TechProfilePath
310 //in order to allow concurrent calls to other dh instances we do not wait for execution here
311 //but doing so we can not indicate problems to the caller (who does what with that then?)
312 //by now we just assume straightforward successful execution
313 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
314 // possible problems to the caller later autonomously
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000315
mpagenko3dbcdd22020-07-22 07:38:45 +0000316 // deadline context to ensure completion of background routines waited for
317 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
318 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
319 dctx, cancel := context.WithDeadline(context.Background(), deadline)
320
mpagenko1cc3cb42020-07-27 15:24:38 +0000321 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000322 var wg sync.WaitGroup
323 wg.Add(2) // for the 2 go routines to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000324 // attention: deadline completion check and wg.Done is to be done in both routines
mpagenkodff5dda2020-08-28 11:52:01 +0000325 go dh.pOnuTP.configureUniTp(dctx, uint8(techProfMsg.UniId), techProfMsg.Path, &wg)
mpagenko3dbcdd22020-07-22 07:38:45 +0000326 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000327 //the wait.. function is responsible for tpProcMutex.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000328 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
mpagenko1cc3cb42020-07-27 15:24:38 +0000329 return err
mpagenkoaf801632020-07-03 10:00:42 +0000330 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000331 // no change, nothing really to do
332 dh.pOnuTP.unlockTpProcMutex()
333 //return success
334 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000335 }
336 case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
337 {
338 if dh.pOnuTP == nil {
339 //should normally not happen ...
340 logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000341 log.Fields{"device-id": dh.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530342 return errors.New("techProfile DelGem request while onuTechProf instance not setup")
mpagenkoaf801632020-07-03 10:00:42 +0000343 }
344
345 msgBody := msg.GetBody()
346 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
347 if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
348 logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000349 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000350 return err
351 }
352
353 //compare TECH_PROFILE_DOWNLOAD_REQUEST
354 dh.pOnuTP.lockTpProcMutex()
mpagenko3dbcdd22020-07-22 07:38:45 +0000355
356 // deadline context to ensure completion of background routines waited for
357 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
358 dctx, cancel := context.WithDeadline(context.Background(), deadline)
359
mpagenko1cc3cb42020-07-27 15:24:38 +0000360 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000361 var wg sync.WaitGroup
362 wg.Add(1) // for the 1 go routine to finish
mpagenko3dbcdd22020-07-22 07:38:45 +0000363 go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000364 cResourceGemPort, delGemPortMsg.GemPortId, &wg)
365 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000366 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
367 return err
mpagenkoaf801632020-07-03 10:00:42 +0000368 }
369 case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
370 {
371 if dh.pOnuTP == nil {
372 //should normally not happen ...
373 logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
divyadesai4d299552020-08-18 07:13:49 +0000374 log.Fields{"device-id": dh.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530375 return errors.New("techProfile DelTcont request while onuTechProf instance not setup")
mpagenkoaf801632020-07-03 10:00:42 +0000376 }
377
378 msgBody := msg.GetBody()
379 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
380 if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
381 logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000382 "device-id": dh.deviceID, "error": err})
mpagenkoaf801632020-07-03 10:00:42 +0000383 return err
384 }
385
386 //compare TECH_PROFILE_DOWNLOAD_REQUEST
387 dh.pOnuTP.lockTpProcMutex()
Himani Chawla4d908332020-08-31 12:30:20 +0530388 if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify {
mpagenko3dbcdd22020-07-22 07:38:45 +0000389 // deadline context to ensure completion of background routines waited for
390 deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
391 dctx, cancel := context.WithDeadline(context.Background(), deadline)
392
mpagenko1cc3cb42020-07-27 15:24:38 +0000393 dh.pOnuTP.resetProcessingErrorIndication()
mpagenkoaf801632020-07-03 10:00:42 +0000394 var wg sync.WaitGroup
mpagenko3dbcdd22020-07-22 07:38:45 +0000395 wg.Add(2) // for the 2 go routines to finish
396 go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
mpagenkoaf801632020-07-03 10:00:42 +0000397 cResourceTcont, delTcontMsg.AllocId, &wg)
398 // Removal of the tcont/alloc id mapping represents the removal of the tech profile
mpagenko3dbcdd22020-07-22 07:38:45 +0000399 go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
mpagenkoaf801632020-07-03 10:00:42 +0000400 //the wait.. function is responsible for tpProcMutex.Unlock()
mpagenko1cc3cb42020-07-27 15:24:38 +0000401 err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
402 return err
mpagenkoaf801632020-07-03 10:00:42 +0000403 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000404 dh.pOnuTP.unlockTpProcMutex()
405 //return success
406 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000407 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000408 default:
409 {
Holger Hildebrandtc54939a2020-06-17 08:14:27 +0000410 logger.Errorw("inter-adapter-unhandled-type", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000411 "device-id": dh.deviceID, "msgType": msg.Header.Type})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000412 return errors.New("unimplemented")
413 }
414 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000415 return nil
416}
417
mpagenkodff5dda2020-08-28 11:52:01 +0000418//FlowUpdateIncremental removes and/or adds the flow changes on a given device
419func (dh *DeviceHandler) FlowUpdateIncremental(apOfFlowChanges *openflow_13.FlowChanges,
420 apOfGroupChanges *openflow_13.FlowGroupChanges, apFlowMetaData *voltha.FlowMetadata) error {
421
422 //Remove flows
423 if apOfFlowChanges.ToRemove != nil {
424 for _, flowItem := range apOfFlowChanges.ToRemove.Items {
425 logger.Debugw("incremental flow item remove", log.Fields{"deviceId": dh.deviceID,
426 "Item": flowItem})
427 }
428 }
429 if apOfFlowChanges.ToAdd != nil {
430 for _, flowItem := range apOfFlowChanges.ToAdd.Items {
431 if flowItem.GetCookie() == 0 {
432 logger.Debugw("incremental flow add - no cookie - ignore", log.Fields{
433 "deviceId": dh.deviceID})
434 continue
435 }
436 flowInPort := flow.GetInPort(flowItem)
437 if flowInPort == uint32(of.OfpPortNo_OFPP_INVALID) {
438 logger.Errorw("flow inPort invalid", log.Fields{"deviceID": dh.deviceID})
439 return errors.New("flow inPort invalid")
440 } else if flowInPort == dh.ponPortNumber {
441 //this is some downstream flow
442 logger.Debugw("incremental flow ignore downstream", log.Fields{
443 "deviceId": dh.deviceID, "inPort": flowInPort})
444 continue
445 } else {
446 // this is the relevant upstream flow
447 var loUniPort *OnuUniPort
448 if uniPort, exist := dh.uniEntityMap[flowInPort]; exist {
449 loUniPort = uniPort
450 } else {
451 logger.Errorw("flow inPort not found in UniPorts",
452 log.Fields{"deviceID": dh.deviceID, "inPort": flowInPort})
453 return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
454 }
455 flowOutPort := flow.GetOutPort(flowItem)
456 logger.Debugw("incremental flow-add port indications", log.Fields{
457 "deviceId": dh.deviceID, "inPort": flowInPort, "outPort": flowOutPort,
458 "uniPortName": loUniPort.name})
459 err := dh.addFlowItemToUniPort(flowItem, loUniPort)
460 //abort processing in error case
461 if err != nil {
462 return err
463 }
464 }
465 }
466 }
467 return nil
468}
469
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000470//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000471// TODO!!! Clarify usage of this method, it is for sure not used within ONOS (OLT) device disable
472// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300473func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000474 logger.Debugw("disable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000475
mpagenko3af1f032020-06-10 08:53:41 +0000476 //admin-lock reason can also be used uniquely for setting the DeviceState accordingly - inblock
477 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
478 if dh.deviceReason != "omci-admin-lock" {
479 // disable UNI ports/ONU
480 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
481 // here the result of the processing is not checked (trusted in background) *****
482 if dh.pLockStateFsm == nil {
483 dh.createUniLockFsm(true, UniAdminStateDone)
484 } else { //LockStateFSM already init
485 dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
486 dh.runUniLockFsm(true)
487 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300488
mpagenko3af1f032020-06-10 08:53:41 +0000489 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000490 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000491 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000492 }
493 dh.deviceReason = "omci-admin-lock"
494 //200604: ConnState improved to 'unreachable' (was not set in python-code), OperState 'unknown' seems to be best choice
495 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
496 voltha.OperStatus_UNKNOWN); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000497 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000498 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +0000499 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300500 }
501}
502
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000503//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
mpagenko3af1f032020-06-10 08:53:41 +0000504// TODO!!! Clarify usage of this method, compare above DisableDevice, usage may clarify resulting states
505// maybe it is obsolete by now
ozgecanetsiafce57b12020-05-25 14:39:35 +0300506func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
divyadesai4d299552020-08-18 07:13:49 +0000507 logger.Debugw("reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
mpagenko3af1f032020-06-10 08:53:41 +0000508
509 // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...(like python code)
ozgecanetsiafce57b12020-05-25 14:39:35 +0300510 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
511 voltha.OperStatus_ACTIVE); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000512 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000513 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300514 }
515
mpagenko3af1f032020-06-10 08:53:41 +0000516 // TODO!!! DeviceReason to be set here could be more accurate, for now just ...(like python code)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000517 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000518 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000519 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiafce57b12020-05-25 14:39:35 +0300520 }
mpagenko3af1f032020-06-10 08:53:41 +0000521 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000522
523 // enable ONU/UNI ports
524 // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
525 // here the result of the processing is not checked (trusted in background) *****
526 if dh.pUnlockStateFsm == nil {
527 dh.createUniLockFsm(false, UniAdminStateDone)
528 } else { //UnlockStateFSM already init
mpagenko3af1f032020-06-10 08:53:41 +0000529 dh.pUnlockStateFsm.SetSuccessEvent(UniAdminStateDone)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000530 dh.runUniLockFsm(false)
531 }
ozgecanetsiafce57b12020-05-25 14:39:35 +0300532}
533
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000534func (dh *DeviceHandler) ReconcileDeviceOnuInd() {
535 logger.Debugw("reconciling - simulate onu indication", log.Fields{"device-id": dh.deviceID})
536
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000537 if err := dh.pOnuTP.restoreFromOnuTpPathKvStore(context.TODO()); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000538 logger.Errorw("reconciling - restoring OnuTp-data failed - abort", log.Fields{"err": err, "device-id": dh.deviceID})
539 dh.reconciling = false
540 return
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000541 }
Himani Chawla4d908332020-08-31 12:30:20 +0530542 var onuIndication oop.OnuIndication
543 onuIndication.IntfId = dh.pOnuTP.sOnuPersistentData.PersIntfID
544 onuIndication.OnuId = dh.pOnuTP.sOnuPersistentData.PersOnuID
545 onuIndication.OperState = dh.pOnuTP.sOnuPersistentData.PersOperState
546 onuIndication.AdminState = dh.pOnuTP.sOnuPersistentData.PersAdminState
547 _ = dh.createInterface(&onuIndication)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000548}
549
550func (dh *DeviceHandler) ReconcileDeviceTechProf() {
551 logger.Debugw("reconciling - trigger tech profile config", log.Fields{"device-id": dh.deviceID})
552
553 dh.pOnuTP.lockTpProcMutex()
554 // lock hangs as long as below decoupled or other related TechProfile processing is active
555 for _, uniData := range dh.pOnuTP.sOnuPersistentData.PersUniTpPath {
556 //In order to allow concurrent calls to other dh instances we do not wait for execution here
557 //but doing so we can not indicate problems to the caller (who does what with that then?)
558 //by now we just assume straightforward successful execution
559 //TODO!!! Generally: In this scheme it would be good to have some means to indicate
560 // possible problems to the caller later autonomously
561
562 // deadline context to ensure completion of background routines waited for
563 //20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
564 deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
565 dctx, cancel := context.WithDeadline(context.Background(), deadline)
566
567 dh.pOnuTP.resetProcessingErrorIndication()
568 var wg sync.WaitGroup
569 wg.Add(1) // for the 1 go routines to finish
570 // attention: deadline completion check and wg.Done is to be done in both routines
mpagenkodff5dda2020-08-28 11:52:01 +0000571 go dh.pOnuTP.configureUniTp(dctx, uint8(uniData.PersUniId), uniData.PersTpPath, &wg)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000572 //the wait.. function is responsible for tpProcMutex.Unlock()
Himani Chawla4d908332020-08-31 12:30:20 +0530573 _ = dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000574 return
575 }
576 dh.pOnuTP.unlockTpProcMutex()
577 //TODO: reset of reconciling-flag has always to be done in the last ReconcileDevice*() function
578 dh.reconciling = false
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000579}
580
581func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000582 logger.Debugw("delete-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000583 if err := dh.pOnuTP.deleteOnuTpPathKvStore(context.TODO()); err != nil {
584 return err
585 }
586 // TODO: further actions - stop metrics and FSMs, remove device ...
587 return nil
588}
589
ozgecanetsiae11479f2020-07-06 09:44:47 +0300590func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
divyadesai4d299552020-08-18 07:13:49 +0000591 logger.Debugw("reboot-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300592 if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
divyadesai4d299552020-08-18 07:13:49 +0000593 logger.Errorw("device-unreachable", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300594 return errors.New("device-unreachable")
595 }
Himani Chawla4d908332020-08-31 12:30:20 +0530596 if err := dh.pOnuOmciDevice.Reboot(context.TODO()); err != nil {
597 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
598 logger.Errorw("error-rebooting-device", log.Fields{"device-id": dh.deviceID, "error": err})
599 return err
600 }
ozgecanetsiae11479f2020-07-06 09:44:47 +0300601 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
602 voltha.OperStatus_DISCOVERED); 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-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300605 return err
606 }
607 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting-onu"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000608 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
divyadesai4d299552020-08-18 07:13:49 +0000609 logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
ozgecanetsiae11479f2020-07-06 09:44:47 +0300610 return err
611 }
612 dh.deviceReason = "rebooting-onu"
613 return nil
614}
615
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000616// DeviceHandler methods that implement the adapters interface requests## end #########
617// #####################################################################################
618
619// ################ to be updated acc. needs of ONU Device ########################
620// DeviceHandler StateMachine related state transition methods ##### begin #########
621
622func (dh *DeviceHandler) logStateChange(e *fsm.Event) {
623 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})
624}
625
626// doStateInit provides the device update to the core
627func (dh *DeviceHandler) doStateInit(e *fsm.Event) {
628
629 logger.Debug("doStateInit-started")
630 var err error
631
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000632 // populate what we know. rest comes later after mib sync
633 dh.device.Root = false
634 dh.device.Vendor = "OpenONU"
635 dh.device.Model = "go"
636 dh.device.Reason = "activating-onu"
mpagenko3af1f032020-06-10 08:53:41 +0000637 dh.deviceReason = "activating-onu"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000638
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000639 dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000640
641 if !dh.reconciling {
Himani Chawla4d908332020-08-31 12:30:20 +0530642 _ = dh.coreProxy.DeviceUpdate(context.TODO(), dh.device)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000643 } else {
644 logger.Debugw("reconciling - don't notify core about DeviceUpdate",
645 log.Fields{"device-id": dh.deviceID})
646 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000647
Himani Chawla4d908332020-08-31 12:30:20 +0530648 dh.parentID = dh.device.ParentId
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000649 dh.ponPortNumber = dh.device.ParentPortNo
650
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000651 // store proxy parameters for later communication - assumption: invariant, else they have to be requested dynamically!!
652 dh.ProxyAddressID = dh.device.ProxyAddress.GetDeviceId()
653 dh.ProxyAddressType = dh.device.ProxyAddress.GetDeviceType()
divyadesai4d299552020-08-18 07:13:49 +0000654 logger.Debugw("device-updated", log.Fields{"device-id": dh.deviceID, "proxyAddressID": dh.ProxyAddressID,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000655 "proxyAddressType": dh.ProxyAddressType, "SNR": dh.device.SerialNumber,
Himani Chawla4d908332020-08-31 12:30:20 +0530656 "ParentId": dh.parentID, "ParentPortNo": dh.ponPortNumber})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000657
658 /*
659 self._pon = PonPort.create(self, self._pon_port_number)
660 self._pon.add_peer(self.parent_id, self._pon_port_number)
661 self.logger.debug('adding-pon-port-to-agent',
662 type=self._pon.get_port().type,
663 admin_state=self._pon.get_port().admin_state,
664 oper_status=self._pon.get_port().oper_status,
665 )
666 */
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000667 if !dh.reconciling {
668 logger.Debugw("adding-pon-port", log.Fields{"deviceID": dh.deviceID, "ponPortNo": dh.ponPortNumber})
669 var ponPortNo uint32 = 1
670 if dh.ponPortNumber != 0 {
671 ponPortNo = dh.ponPortNumber
672 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000673
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000674 pPonPort := &voltha.Port{
675 PortNo: ponPortNo,
676 Label: fmt.Sprintf("pon-%d", ponPortNo),
677 Type: voltha.Port_PON_ONU,
678 OperStatus: voltha.OperStatus_ACTIVE,
Himani Chawla4d908332020-08-31 12:30:20 +0530679 Peers: []*voltha.Port_PeerPort{{DeviceId: dh.parentID, // Peer device is OLT
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000680 PortNo: ponPortNo}}, // Peer port is parent's port number
681 }
682 if err = dh.coreProxy.PortCreated(context.TODO(), dh.deviceID, pPonPort); err != nil {
683 logger.Fatalf("Device FSM: PortCreated-failed-%s", err)
684 e.Cancel(err)
685 return
686 }
687 } else {
688 logger.Debugw("reconciling - pon-port already added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000689 }
690 logger.Debug("doStateInit-done")
691}
692
693// postInit setups the DeviceEntry for the conerned device
694func (dh *DeviceHandler) postInit(e *fsm.Event) {
695
696 logger.Debug("postInit-started")
697 var err error
698 /*
699 dh.Client = oop.NewOpenoltClient(dh.clientCon)
700 dh.pTransitionMap.Handle(ctx, GrpcConnected)
701 return nil
702 */
mpagenko3af1f032020-06-10 08:53:41 +0000703 if err = dh.AddOnuDeviceEntry(context.TODO()); err != nil {
704 logger.Fatalf("Device FSM: AddOnuDeviceEntry-failed-%s", err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000705 e.Cancel(err)
706 return
707 }
708
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000709 if dh.reconciling {
710 go dh.ReconcileDeviceOnuInd()
711 // reconcilement will be continued after mib download is done
712 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000713 /*
714 ############################################################################
715 # Setup Alarm handler
716 self.events = AdapterEvents(self.core_proxy, device.id, self.logical_device_id,
717 device.serial_number)
718 ############################################################################
719 # Setup PM configuration for this device
720 # Pass in ONU specific options
721 kwargs = {
722 OnuPmMetrics.DEFAULT_FREQUENCY_KEY: OnuPmMetrics.DEFAULT_ONU_COLLECTION_FREQUENCY,
723 'heartbeat': self.heartbeat,
724 OnuOmciPmMetrics.OMCI_DEV_KEY: self._onu_omci_device
725 }
726 self.logger.debug('create-pm-metrics', device_id=device.id, serial_number=device.serial_number)
727 self._pm_metrics = OnuPmMetrics(self.events, self.core_proxy, self.device_id,
728 self.logical_device_id, device.serial_number,
729 grouped=True, freq_override=False, **kwargs)
730 pm_config = self._pm_metrics.make_proto()
731 self._onu_omci_device.set_pm_config(self._pm_metrics.omci_pm.openomci_interval_pm)
732 self.logger.info("initial-pm-config", device_id=device.id, serial_number=device.serial_number)
733 yield self.core_proxy.device_pm_config_update(pm_config, init=True)
734
735 # Note, ONU ID and UNI intf set in add_uni_port method
736 self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.events,
737 ani_ports=[self._pon])
738
739 # Code to Run OMCI Test Action
740 kwargs_omci_test_action = {
741 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
742 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
743 }
744 serial_number = device.serial_number
745 self._test_request = OmciTestRequest(self.core_proxy,
746 self.omci_agent, self.device_id,
747 AniG, serial_number,
748 self.logical_device_id,
749 exclusive=False,
750 **kwargs_omci_test_action)
751
752 self.enabled = True
753 else:
754 self.logger.info('onu-already-activated')
755 */
756 logger.Debug("postInit-done")
757}
758
759// doStateConnected get the device info and update to voltha core
760// for comparison of the original method (not that easy to uncomment): compare here:
761// voltha-openolt-adapter/adaptercore/device_handler.go
762// -> this one obviously initiates all communication interfaces of the device ...?
763func (dh *DeviceHandler) doStateConnected(e *fsm.Event) {
764
765 logger.Debug("doStateConnected-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530766 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000767 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000768 logger.Debug("doStateConnected-done")
769}
770
771// doStateUp handle the onu up indication and update to voltha core
772func (dh *DeviceHandler) doStateUp(e *fsm.Event) {
773
774 logger.Debug("doStateUp-started")
Himani Chawla4d908332020-08-31 12:30:20 +0530775 err := errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000776 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000777 logger.Debug("doStateUp-done")
778
779 /*
780 // Synchronous call to update device state - this method is run in its own go routine
781 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
782 voltha.OperStatus_ACTIVE); err != nil {
783 logger.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
784 return err
785 }
786 return nil
787 */
788}
789
790// doStateDown handle the onu down indication
791func (dh *DeviceHandler) doStateDown(e *fsm.Event) {
792
793 logger.Debug("doStateDown-started")
794 var err error
795
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000796 device := dh.device
797 if device == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000798 /*TODO: needs to handle error scenarios */
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000799 logger.Error("Failed to fetch handler device")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000800 e.Cancel(err)
801 return
802 }
803
804 cloned := proto.Clone(device).(*voltha.Device)
805 logger.Debugw("do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
806 /*
807 // Update the all ports state on that device to disable
808 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
809 logger.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
810 return er
811 }
812
813 //Update the device oper state and connection status
814 cloned.OperStatus = voltha.OperStatus_UNKNOWN
815 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
816 dh.device = cloned
817
818 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
819 logger.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
820 return er
821 }
822
823 //get the child device for the parent device
824 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
825 if err != nil {
826 logger.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
827 return err
828 }
829 for _, onuDevice := range onuDevices.Items {
830
831 // Update onu state as down in onu adapter
832 onuInd := oop.OnuIndication{}
833 onuInd.OperState = "down"
834 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
835 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
836 if er != nil {
837 logger.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
838 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
839 //Do not return here and continue to process other ONUs
840 }
841 }
842 // * Discovered ONUs entries need to be cleared , since after OLT
843 // is up, it starts sending discovery indications again* /
844 dh.discOnus = sync.Map{}
845 logger.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
846 return nil
847 */
Himani Chawla4d908332020-08-31 12:30:20 +0530848 err = errors.New("device FSM: function not implemented yet")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000849 e.Cancel(err)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000850 logger.Debug("doStateDown-done")
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(
Himani Chawla4d908332020-08-31 12:30:20 +0530885 apDeviceEntry *OnuDeviceEntry, apOnuTp *OnuUniTechProf) {
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}
891
mpagenko3af1f032020-06-10 08:53:41 +0000892//AddOnuDeviceEntry creates a new ONU device or returns the existing
893func (dh *DeviceHandler) AddOnuDeviceEntry(ctx context.Context) error {
divyadesai4d299552020-08-18 07:13:49 +0000894 logger.Debugw("adding-deviceEntry", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000895
mpagenko3af1f032020-06-10 08:53:41 +0000896 deviceEntry := dh.GetOnuDeviceEntry(false)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000897 if deviceEntry == nil {
898 /* costum_me_map in python code seems always to be None,
899 we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
900 /* also no 'clock' argument - usage open ...*/
901 /* and no alarm_db yet (oo.alarm_db) */
mpagenkoaf801632020-07-03 10:00:42 +0000902 deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost,
903 dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000904 dh, dh.coreProxy, dh.AdapterProxy,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000905 dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
mpagenkoaf801632020-07-03 10:00:42 +0000906 onuTechProfProc := NewOnuUniTechProf(ctx, dh.deviceID, dh)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000907 //error treatment possible //TODO!!!
mpagenkoaf801632020-07-03 10:00:42 +0000908 dh.SetOnuDeviceEntry(deviceEntry, onuTechProfProc)
mpagenko3af1f032020-06-10 08:53:41 +0000909 // fire deviceEntry ready event to spread to possibly waiting processing
910 dh.deviceEntrySet <- true
divyadesai4d299552020-08-18 07:13:49 +0000911 logger.Infow("onuDeviceEntry-added", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000912 } else {
divyadesai4d299552020-08-18 07:13:49 +0000913 logger.Infow("onuDeviceEntry-add: Device already exists", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000914 }
915 // might be updated with some error handling !!!
916 return nil
917}
918
919// doStateInit provides the device update to the core
Himani Chawla4d908332020-08-31 12:30:20 +0530920func (dh *DeviceHandler) createInterface(onuind *oop.OnuIndication) error {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000921 logger.Debugw("create_interface-started", log.Fields{"OnuId": onuind.GetOnuId(),
922 "OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
923
924 dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000925
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000926 if !dh.reconciling {
927 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
928 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVATING); err != nil {
929 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
930 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
931 }
932 } else {
933 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVATING",
934 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000935 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000936 // It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
937 // in this code the GetDevice would just make a check if the DeviceID's Device still exists in core
938 // 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 +0000939 // 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 +0000940 // so let's just try to keep it simple ...
941 /*
942 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
943 if err != nil || device == nil {
944 //TODO: needs to handle error scenarios
945 logger.Errorw("Failed to fetch device device at creating If", log.Fields{"err": err})
946 return errors.New("Voltha Device not found")
947 }
948 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000949
mpagenko3af1f032020-06-10 08:53:41 +0000950 pDevEntry := dh.GetOnuDeviceEntry(true)
951 if pDevEntry != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530952 if err := pDevEntry.Start(context.TODO()); err != nil {
953 return err
954 }
mpagenko3af1f032020-06-10 08:53:41 +0000955 } else {
divyadesai4d299552020-08-18 07:13:49 +0000956 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530957 return errors.New("no valid OnuDevice")
mpagenko3af1f032020-06-10 08:53:41 +0000958 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +0000959 if !dh.reconciling {
960 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "starting-openomci"); err != nil {
961 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
962 logger.Errorw("error-DeviceReasonUpdate to starting-openomci", log.Fields{"device-id": dh.deviceID, "error": err})
963 }
964 } else {
965 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to starting-openomci",
966 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000967 }
mpagenko3af1f032020-06-10 08:53:41 +0000968 dh.deviceReason = "starting-openomci"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000969
970 /* this might be a good time for Omci Verify message? */
971 verifyExec := make(chan bool)
Himani Chawla4d908332020-08-31 12:30:20 +0530972 omciVerify := NewOmciTestRequest(context.TODO(),
mpagenko3af1f032020-06-10 08:53:41 +0000973 dh.device.Id, pDevEntry.PDevOmciCC,
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000974 true, true) //eclusive and allowFailure (anyway not yet checked)
Himani Chawla4d908332020-08-31 12:30:20 +0530975 omciVerify.PerformOmciTest(context.TODO(), verifyExec)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000976
977 /* give the handler some time here to wait for the OMCi verification result
978 after Timeout start and try MibUpload FSM anyway
979 (to prevent stopping on just not supported OMCI verification from ONU) */
980 select {
981 case <-time.After(2 * time.Second):
982 logger.Warn("omci start-verification timed out (continue normal)")
983 case testresult := <-verifyExec:
984 logger.Infow("Omci start verification done", log.Fields{"result": testresult})
985 }
986
987 /* In py code it looks earlier (on activate ..)
988 # Code to Run OMCI Test Action
989 kwargs_omci_test_action = {
990 OmciTestRequest.DEFAULT_FREQUENCY_KEY:
991 OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY
992 }
993 serial_number = device.serial_number
994 self._test_request = OmciTestRequest(self.core_proxy,
995 self.omci_agent, self.device_id,
996 AniG, serial_number,
997 self.logical_device_id,
998 exclusive=False,
999 **kwargs_omci_test_action)
1000 ...
1001 # Start test requests after a brief pause
1002 if not self._test_request_started:
1003 self._test_request_started = True
1004 tststart = _STARTUP_RETRY_WAIT * (random.randint(1, 5))
1005 reactor.callLater(tststart, self._test_request.start_collector)
1006
1007 */
1008 /* which is then: in omci_test_request.py : */
1009 /*
1010 def start_collector(self, callback=None):
1011 """
1012 Start the collection loop for an adapter if the frequency > 0
1013
1014 :param callback: (callable) Function to call to collect PM data
1015 """
1016 self.logger.info("starting-pm-collection", device_name=self.name, default_freq=self.default_freq)
1017 if callback is None:
1018 callback = self.perform_test_omci
1019
1020 if self.lc is None:
1021 self.lc = LoopingCall(callback)
1022
1023 if self.default_freq > 0:
1024 self.lc.start(interval=self.default_freq / 10)
1025
1026 def perform_test_omci(self):
1027 """
1028 Perform the initial test request
1029 """
1030 ani_g_entities = self._device.configuration.ani_g_entities
1031 ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
1032 is not None else None
1033 self._entity_id = ani_g_entities_ids[0]
1034 self.logger.info('perform-test', entity_class=self._entity_class,
1035 entity_id=self._entity_id)
1036 try:
1037 frame = MEFrame(self._entity_class, self._entity_id, []).test()
1038 result = yield self._device.omci_cc.send(frame)
1039 if not result.fields['omci_message'].fields['success_code']:
1040 self.logger.info('Self-Test Submitted Successfully',
1041 code=result.fields[
1042 'omci_message'].fields['success_code'])
1043 else:
1044 raise TestFailure('Test Failure: {}'.format(
1045 result.fields['omci_message'].fields['success_code']))
1046 except TimeoutError as e:
1047 self.deferred.errback(failure.Failure(e))
1048
1049 except Exception as e:
1050 self.logger.exception('perform-test-Error', e=e,
1051 class_id=self._entity_class,
1052 entity_id=self._entity_id)
1053 self.deferred.errback(failure.Failure(e))
1054
1055 */
1056
1057 // PM related heartbeat??? !!!TODO....
1058 //self._heartbeat.enabled = True
1059
mpagenko1cc3cb42020-07-27 15:24:38 +00001060 /* Note: Even though FSM calls look 'synchronous' here, FSM is running in background with the effect that possible errors
1061 * within the MibUpload are not notified in the OnuIndication response, this might be acceptable here,
1062 * as further OltAdapter processing may rely on the deviceReason event 'MibUploadDone' as a result of the FSM processing
Himani Chawla4d908332020-08-31 12:30:20 +05301063 * otherwise some processing synchronization would be required - cmp. e.g TechProfile processing
mpagenko1cc3cb42020-07-27 15:24:38 +00001064 */
1065 //call MibUploadFSM - transition up to state ulStInSync
mpagenko3af1f032020-06-10 08:53:41 +00001066 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001067 if pMibUlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001068 if pMibUlFsm.Is(ulStDisabled) {
1069 if err := pMibUlFsm.Event(ulEvStart); err != nil {
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001070 logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
Himani Chawla4d908332020-08-31 12:30:20 +05301071 return errors.New("can't go to state starting")
1072 }
1073 logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1074 //Determine ONU status and start/re-start MIB Synchronization tasks
1075 //Determine if this ONU has ever synchronized
1076 if true { //TODO: insert valid check
1077 if err := pMibUlFsm.Event(ulEvResetMib); err != nil {
1078 logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
1079 return errors.New("can't go to state resetting_mib")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001080 }
Himani Chawla4d908332020-08-31 12:30:20 +05301081 } else {
1082 if err := pMibUlFsm.Event(ulEvExamineMds); err != nil {
1083 logger.Errorw("MibSyncFsm: Can't go to state examine_mds", log.Fields{"err": err})
1084 return errors.New("can't go to examine_mds")
1085 }
1086 logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
1087 //Examine the MIB Data Sync
1088 // callbacks to be handled:
1089 // Event(ulEvSuccess)
1090 // Event(ulEvTimeout)
1091 // Event(ulEvMismatch)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001092 }
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001093 } else {
1094 logger.Errorw("wrong state of MibSyncFsm - want: disabled", log.Fields{"have": string(pMibUlFsm.Current())})
1095 return errors.New("wrong state of MibSyncFsm")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001096 }
1097 } else {
divyadesai4d299552020-08-18 07:13:49 +00001098 logger.Errorw("MibSyncFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001099 return errors.New("cannot execut MibSync")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001100 }
1101 return nil
1102}
1103
mpagenko3af1f032020-06-10 08:53:41 +00001104func (dh *DeviceHandler) updateInterface(onuind *oop.OnuIndication) error {
1105 //state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
1106 if dh.deviceReason != "stopping-openomci" {
divyadesai4d299552020-08-18 07:13:49 +00001107 logger.Debugw("updateInterface-started - stopping-device", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001108 //stop all running SM processing - make use of the DH-state as mirrored in the deviceReason
1109 pDevEntry := dh.GetOnuDeviceEntry(false)
1110 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001111 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301112 return errors.New("no valid OnuDevice")
mpagenko3af1f032020-06-10 08:53:41 +00001113 }
1114
1115 switch dh.deviceReason {
1116 case "starting-openomci":
1117 { //MIBSync FSM may run
1118 pMibUlFsm := pDevEntry.pMibUploadFsm.pFsm
1119 if pMibUlFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301120 _ = pMibUlFsm.Event(ulEvStop) //TODO!! verify if MibSyncFsm stop-processing is sufficient (to allow it again afterwards)
mpagenko3af1f032020-06-10 08:53:41 +00001121 }
1122 }
1123 case "discovery-mibsync-complete":
1124 { //MibDownload may run
1125 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
1126 if pMibDlFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301127 _ = pMibDlFsm.Event(dlEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001128 }
1129 }
1130 default:
mpagenko3dbcdd22020-07-22 07:38:45 +00001131 {
1132 //port lock/unlock FSM's may be active
mpagenko3af1f032020-06-10 08:53:41 +00001133 if dh.pUnlockStateFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301134 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001135 }
1136 if dh.pLockStateFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301137 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
mpagenko3af1f032020-06-10 08:53:41 +00001138 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001139 //techProfile related PonAniConfigFsm FSM may be active
1140 // maybe encapsulated as OnuTP method - perhaps later in context of module splitting
1141 if dh.pOnuTP.pAniConfigFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301142 _ = dh.pOnuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +00001143 }
mpagenkodff5dda2020-08-28 11:52:01 +00001144 for _, uniPort := range dh.uniEntityMap {
1145 //reset the TechProfileConfig Done state for all (active) UNI's
1146 dh.pOnuTP.setConfigDone(uniPort.uniId, false)
1147 // reset tjhe possibly existing VlanConfigFsm
1148 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[uniPort.uniId]; exist {
1149 //VlanFilterFsm exists and was already started
1150 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1151 if pVlanFilterStatemachine != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301152 _ = pVlanFilterStatemachine.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001153 }
1154 }
1155 }
mpagenko3af1f032020-06-10 08:53:41 +00001156 }
1157 //TODO!!! care about PM/Alarm processing once started
1158 }
1159 //TODO: from here the deviceHandler FSM itself may be stuck in some of the initial states
Himani Chawla4d908332020-08-31 12:30:20 +05301160 // (mainly the still separate 'Event states')
mpagenko3af1f032020-06-10 08:53:41 +00001161 // so it is questionable, how this is resolved after some possible re-enable
1162 // assumption there is obviously, that the system may continue with some 'after "mib-download-done" state'
1163
1164 //stop/remove(?) the device entry
Himani Chawla4d908332020-08-31 12:30:20 +05301165 _ = pDevEntry.Stop(context.TODO()) //maybe some more sophisticated context treatment should be used here?
mpagenko3af1f032020-06-10 08:53:41 +00001166
1167 //TODO!!! remove existing traffic profiles
1168 /* from py code, if TP's exist, remove them - not yet implemented
1169 self._tp = dict()
1170 # Let TP download happen again
1171 for uni_id in self._tp_service_specific_task:
1172 self._tp_service_specific_task[uni_id].clear()
1173 for uni_id in self._tech_profile_download_done:
1174 self._tech_profile_download_done[uni_id].clear()
1175 */
1176
1177 dh.disableUniPortStateUpdate()
1178
1179 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001180 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001181 logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
divyadesai4d299552020-08-18 07:13:49 +00001182 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001183 // abort: system behavior is just unstable ...
1184 return err
1185 }
1186 dh.deviceReason = "stopping-openomci"
1187
1188 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1189 voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_DISCOVERED); err != nil {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001190 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
mpagenko3af1f032020-06-10 08:53:41 +00001191 logger.Errorw("error-updating-device-state unreachable-discovered",
divyadesai4d299552020-08-18 07:13:49 +00001192 log.Fields{"device-id": dh.deviceID, "error": err})
mpagenko3af1f032020-06-10 08:53:41 +00001193 // abort: system behavior is just unstable ...
1194 return err
1195 }
1196 } else {
divyadesai4d299552020-08-18 07:13:49 +00001197 logger.Debugw("updateInterface - device already stopped", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001198 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001199 return nil
1200}
1201
mpagenko3af1f032020-06-10 08:53:41 +00001202//DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
Himani Chawla4d908332020-08-31 12:30:20 +05301203func (dh *DeviceHandler) DeviceProcStatusUpdate(devEvent OnuDeviceEvent) {
1204 switch devEvent {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001205 case MibDatabaseSync:
1206 {
divyadesai4d299552020-08-18 07:13:49 +00001207 logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001208 if !dh.reconciling {
1209 //initiate DevStateUpdate
1210 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
1211 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1212 logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
1213 "device-id": dh.deviceID, "error": err})
1214 } else {
1215 logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
1216 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001217 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001218 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
1219 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001220 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001221 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001222 dh.deviceReason = "discovery-mibsync-complete"
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001223
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001224 i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001225 pDevEntry := dh.GetOnuDeviceEntry(false)
1226 if unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
Himani Chawla4d908332020-08-31 12:30:20 +05301227 for _, mgmtEntityID := range unigInstKeys {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001228 logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
Himani Chawla4d908332020-08-31 12:30:20 +05301229 "device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityID})
1230 dh.addUniPort(mgmtEntityID, i, UniPPTP)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001231 i++
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001232 }
1233 } else {
divyadesai4d299552020-08-18 07:13:49 +00001234 logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +00001235 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001236 if veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
Himani Chawla4d908332020-08-31 12:30:20 +05301237 for _, mgmtEntityID := range veipInstKeys {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001238 logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
Himani Chawla4d908332020-08-31 12:30:20 +05301239 "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
1240 dh.addUniPort(mgmtEntityID, i, UniVEIP)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001241 i++
1242 }
1243 } else {
divyadesai4d299552020-08-18 07:13:49 +00001244 logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001245 }
1246 if i == 0 {
divyadesai4d299552020-08-18 07:13:49 +00001247 logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001248 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001249
mpagenko3af1f032020-06-10 08:53:41 +00001250 /* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
1251 * left the code here as comment in case such processing should prove needed unexpectedly
1252 // Init Uni Ports to Admin locked state
1253 // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
1254 // *** should generate UniLockStateDone event *****
1255 if dh.pLockStateFsm == nil {
1256 dh.createUniLockFsm(true, UniLockStateDone)
1257 } else { //LockStateFSM already init
1258 dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
1259 dh.runUniLockFsm(true)
1260 }
1261 }
1262 case UniLockStateDone:
1263 {
divyadesai4d299552020-08-18 07:13:49 +00001264 logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001265 * lockState processing commented out
1266 */
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001267 /* Mib download procedure -
1268 ***** should run over 'downloaded' state and generate MibDownloadDone event *****
1269 */
mpagenko3af1f032020-06-10 08:53:41 +00001270 pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001271 if pMibDlFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001272 if pMibDlFsm.Is(dlStDisabled) {
1273 if err := pMibDlFsm.Event(dlEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001274 logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
1275 // maybe try a FSM reset and then again ... - TODO!!!
1276 } else {
1277 logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1278 // maybe use more specific states here for the specific download steps ...
mpagenko1cc3cb42020-07-27 15:24:38 +00001279 if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001280 logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
1281 } else {
1282 logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
1283 //Begin MIB data download (running autonomously)
1284 }
1285 }
1286 } else {
1287 logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
1288 // maybe try a FSM reset and then again ... - TODO!!!
1289 }
1290 /***** Mib download started */
1291 } else {
divyadesai4d299552020-08-18 07:13:49 +00001292 logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001293 }
1294 }
1295 case MibDownloadDone:
1296 {
divyadesai4d299552020-08-18 07:13:49 +00001297 logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001298 //initiate DevStateUpdate
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001299 if !dh.reconciling {
1300 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
1301 voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
1302 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1303 logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
1304 } else {
1305 logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
1306 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001307 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001308 logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
1309 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001310 }
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001311 if !dh.reconciling {
1312 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
1313 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1314 logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
1315 log.Fields{"device-id": dh.deviceID, "error": err})
1316 } else {
1317 logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
1318 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001319 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001320 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
1321 log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001322 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001323 //set internal state anyway - as it was done
mpagenko3af1f032020-06-10 08:53:41 +00001324 dh.deviceReason = "initial-mib-downloaded"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001325 // *** should generate UniUnlockStateDone event *****
1326 if dh.pUnlockStateFsm == nil {
1327 dh.createUniLockFsm(false, UniUnlockStateDone)
1328 } else { //UnlockStateFSM already init
1329 dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
1330 dh.runUniLockFsm(false)
1331 }
1332 }
1333 case UniUnlockStateDone:
1334 {
mpagenko3af1f032020-06-10 08:53:41 +00001335 go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001336
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001337 if !dh.reconciling {
1338 logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
1339 raisedTs := time.Now().UnixNano()
1340 go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
1341 } else {
1342 logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
1343 log.Fields{"device-id": dh.deviceID})
1344 go dh.ReconcileDeviceTechProf()
1345 //TODO: further actions e.g. restore flows, metrics, ...
1346 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001347 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001348 case OmciAniConfigDone:
1349 {
divyadesai4d299552020-08-18 07:13:49 +00001350 logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001351 // attention: the device reason update is done based on ONU-UNI-Port related activity
1352 // - which may cause some inconsistency
1353 if dh.deviceReason != "tech-profile-config-download-success" {
1354 // which may be the case from some previous actvity on another UNI Port of the ONU
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001355 if !dh.reconciling {
1356 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
1357 //TODO with VOL-3045/VOL-3046: return the error and stop further processing
1358 logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
1359 log.Fields{"device-id": dh.deviceID, "error": err})
1360 } else {
1361 logger.Infow("update dev reason to 'tech-profile-config-download-success'",
1362 log.Fields{"device-id": dh.deviceID})
1363 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001364 } else {
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001365 logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
divyadesai4d299552020-08-18 07:13:49 +00001366 log.Fields{"device-id": dh.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001367 }
1368 //set internal state anyway - as it was done
1369 dh.deviceReason = "tech-profile-config-download-success"
1370 }
1371 }
mpagenkodff5dda2020-08-28 11:52:01 +00001372 case OmciVlanFilterDone:
1373 {
1374 logger.Debugw("OmciVlanFilterDone event received",
1375 log.Fields{"device-id": dh.deviceID})
1376 // attention: the device reason update is done based on ONU-UNI-Port related activity
1377 // - which may cause some inconsistency
1378 // yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
1379
1380 if dh.deviceReason != "omci-flows-pushed" {
1381 // which may be the case from some previous actvity on another UNI Port of the ONU
1382 // or even some previous flow add activity on the same port
1383 if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
1384 logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
1385 log.Fields{"device-id": dh.deviceID, "error": err})
1386 } else {
1387 logger.Infow("updated dev reason to ''omci-flows-pushed'",
1388 log.Fields{"device-id": dh.deviceID})
1389 }
1390 //set internal state anyway - as it was done
1391 dh.deviceReason = "omci-flows-pushed"
1392 }
1393 }
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001394 default:
1395 {
Himani Chawla4d908332020-08-31 12:30:20 +05301396 logger.Warnw("unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": devEvent})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001397 }
1398 } //switch
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001399}
1400
Himani Chawla4d908332020-08-31 12:30:20 +05301401func (dh *DeviceHandler) addUniPort(aUniInstNo uint16, aUniID uint8, aPortType UniPortType) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001402 // parameters are IntfId, OnuId, uniId
1403 uniNo := MkUniPortNum(dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(),
Himani Chawla4d908332020-08-31 12:30:20 +05301404 uint32(aUniID))
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001405 if _, present := dh.uniEntityMap[uniNo]; present {
Himani Chawla4d908332020-08-31 12:30:20 +05301406 logger.Warnw("onuUniPort-add: Port already exists", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001407 } else {
Himani Chawla4d908332020-08-31 12:30:20 +05301408 //with arguments aUniID, a_portNo, aPortType
1409 pUniPort := NewOnuUniPort(aUniID, uniNo, aUniInstNo, aPortType)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001410 if pUniPort == nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301411 logger.Warnw("onuUniPort-add: Could not create Port", log.Fields{"for InstanceId": aUniInstNo})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001412 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001413 //store UniPort with the System-PortNumber key
1414 dh.uniEntityMap[uniNo] = pUniPort
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001415 if !dh.reconciling {
1416 // create announce the UniPort to the core as VOLTHA Port object
1417 if err := pUniPort.CreateVolthaPort(dh); err == nil {
1418 logger.Infow("onuUniPort-added", log.Fields{"for PortNo": uniNo})
1419 } //error logging already within UniPort method
1420 } else {
1421 logger.Debugw("reconciling - onuUniPort already added", log.Fields{"for PortNo": uniNo, "device-id": dh.deviceID})
1422 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001423 }
1424 }
1425}
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001426
mpagenko3af1f032020-06-10 08:53:41 +00001427// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
1428func (dh *DeviceHandler) enableUniPortStateUpdate() {
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001429 // py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
Himani Chawla4d908332020-08-31 12:30:20 +05301430 // but towards core only the first port active state is signaled
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001431 // with following remark:
1432 // # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
1433 // # load on the core
1434
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001435 // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001436
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001437 for uniNo, uniPort := range dh.uniEntityMap {
mpagenko3af1f032020-06-10 08:53:41 +00001438 // only if this port is validated for operState transfer
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001439 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1440 logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
1441 uniPort.SetOperState(vc.OperStatus_ACTIVE)
Holger Hildebrandtf41a1602020-08-19 09:52:50 +00001442 if !dh.reconciling {
1443 //maybe also use getter functions on uniPort - perhaps later ...
1444 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
1445 } else {
1446 logger.Debugw("reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
1447 }
mpagenko3af1f032020-06-10 08:53:41 +00001448 }
1449 }
1450}
1451
1452// Disable UniPortState and update core port state accordingly
1453func (dh *DeviceHandler) disableUniPortStateUpdate() {
1454 // compare enableUniPortStateUpdate() above
1455 // -> use current restriction to operate only on first UNI port as inherited from actual Py code
1456 for uniNo, uniPort := range dh.uniEntityMap {
1457 // only if this port is validated for operState transfer
1458 if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
1459 logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
1460 uniPort.SetOperState(vc.OperStatus_UNKNOWN)
1461 //maybe also use getter functions on uniPort - perhaps later ...
1462 go dh.coreProxy.PortStateUpdate(context.TODO(), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
Holger Hildebrandtbe674422020-05-05 13:05:30 +00001463 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001464 }
1465}
1466
1467// ONU_Active/Inactive announcement on system KAFKA bus
1468// tried to re-use procedure of oltUpDownIndication from openolt_eventmgr.go with used values from Py code
Himani Chawla4d908332020-08-31 12:30:20 +05301469func (dh *DeviceHandler) sendOnuOperStateEvent(aOperState vc.OperStatus_Types, aDeviceID string, raisedTs int64) {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001470 var de voltha.DeviceEvent
1471 eventContext := make(map[string]string)
1472 //Populating event context
1473 // assume giving ParentId in GetDevice twice really gives the ParentDevice (there is no GetParentDevice()...)
Himani Chawla4d908332020-08-31 12:30:20 +05301474 parentDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.parentID, dh.parentID)
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001475 if err != nil || parentDevice == nil {
1476 logger.Errorw("Failed to fetch parent device for OnuEvent",
Himani Chawla4d908332020-08-31 12:30:20 +05301477 log.Fields{"parentID": dh.parentID, "err": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001478 }
1479 oltSerialNumber := parentDevice.SerialNumber
1480
1481 eventContext["pon-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.IntfId), 10)
1482 eventContext["onu-id"] = strconv.FormatUint(uint64(dh.pOnuIndication.OnuId), 10)
1483 eventContext["serial-number"] = dh.device.SerialNumber
1484 eventContext["olt_serial_number"] = oltSerialNumber
Himani Chawla4d908332020-08-31 12:30:20 +05301485 eventContext["device_id"] = aDeviceID
1486 eventContext["registration_id"] = aDeviceID //py: string(device_id)??
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001487 logger.Debugw("prepare ONU_ACTIVATED event",
Himani Chawla4d908332020-08-31 12:30:20 +05301488 log.Fields{"DeviceId": aDeviceID, "EventContext": eventContext})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001489
1490 /* Populating device event body */
1491 de.Context = eventContext
Himani Chawla4d908332020-08-31 12:30:20 +05301492 de.ResourceId = aDeviceID
1493 if aOperState == voltha.OperStatus_ACTIVE {
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001494 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "RAISE_EVENT")
1495 de.Description = fmt.Sprintf("%s Event - %s - %s",
1496 cEventObjectType, cOnuActivatedEvent, "Raised")
1497 } else {
1498 de.DeviceEventName = fmt.Sprintf("%s_%s", cOnuActivatedEvent, "CLEAR_EVENT")
1499 de.Description = fmt.Sprintf("%s Event - %s - %s",
1500 cEventObjectType, cOnuActivatedEvent, "Cleared")
1501 }
1502 /* Send event to KAFKA */
1503 if err := dh.EventProxy.SendDeviceEvent(&de, equipment, pon, raisedTs); err != nil {
1504 logger.Warnw("could not send ONU_ACTIVATED event",
Himani Chawla4d908332020-08-31 12:30:20 +05301505 log.Fields{"device-id": aDeviceID, "error": err})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001506 }
1507 logger.Debugw("ONU_ACTIVATED event sent to KAFKA",
Himani Chawla4d908332020-08-31 12:30:20 +05301508 log.Fields{"device-id": aDeviceID, "with-EventName": de.DeviceEventName})
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001509}
1510
Himani Chawla4d908332020-08-31 12:30:20 +05301511// createUniLockFsm initializes and runs the UniLock FSM to transfer the OMCI related commands for port lock/unlock
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001512func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
1513 chLSFsm := make(chan Message, 2048)
1514 var sFsmName string
Himani Chawla4d908332020-08-31 12:30:20 +05301515 if aAdminState {
divyadesai4d299552020-08-18 07:13:49 +00001516 logger.Infow("createLockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001517 sFsmName = "LockStateFSM"
1518 } else {
divyadesai4d299552020-08-18 07:13:49 +00001519 logger.Infow("createUnlockStateFSM", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001520 sFsmName = "UnLockStateFSM"
1521 }
mpagenko3af1f032020-06-10 08:53:41 +00001522
1523 pDevEntry := dh.GetOnuDeviceEntry(true)
1524 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +00001525 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
mpagenko3af1f032020-06-10 08:53:41 +00001526 return
1527 }
1528 pLSFsm := NewLockStateFsm(pDevEntry.PDevOmciCC, aAdminState, devEvent,
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001529 sFsmName, dh.deviceID, chLSFsm)
1530 if pLSFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301531 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001532 dh.pLockStateFsm = pLSFsm
1533 } else {
1534 dh.pUnlockStateFsm = pLSFsm
1535 }
1536 dh.runUniLockFsm(aAdminState)
1537 } else {
divyadesai4d299552020-08-18 07:13:49 +00001538 logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001539 }
1540}
1541
1542// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
1543func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
1544 /* Uni Port lock/unlock procedure -
1545 ***** should run via 'adminDone' state and generate the argument requested event *****
1546 */
1547 var pLSStatemachine *fsm.FSM
Himani Chawla4d908332020-08-31 12:30:20 +05301548 if aAdminState {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001549 pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
1550 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1551 if (dh.pUnlockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001552 (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301553 _ = dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001554 }
1555 } else {
1556 pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
1557 //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
1558 if (dh.pLockStateFsm != nil) &&
mpagenko1cc3cb42020-07-27 15:24:38 +00001559 (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != uniStDisabled) {
Himani Chawla4d908332020-08-31 12:30:20 +05301560 _ = dh.pLockStateFsm.pAdaptFsm.pFsm.Event(uniEvReset)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001561 }
1562 }
1563 if pLSStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +00001564 if pLSStatemachine.Is(uniStDisabled) {
1565 if err := pLSStatemachine.Event(uniEvStart); err != nil {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001566 logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
1567 // maybe try a FSM reset and then again ... - TODO!!!
1568 } else {
1569 /***** LockStateFSM started */
1570 logger.Debugw("LockStateFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001571 "state": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001572 }
1573 } else {
1574 logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +00001575 "have": pLSStatemachine.Current(), "device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001576 // maybe try a FSM reset and then again ... - TODO!!!
1577 }
1578 } else {
divyadesai4d299552020-08-18 07:13:49 +00001579 logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +00001580 // maybe try a FSM reset and then again ... - TODO!!!
1581 }
1582}
1583
mpagenkoaf801632020-07-03 10:00:42 +00001584//SetBackend provides a DB backend for the specified path on the existing KV client
1585func (dh *DeviceHandler) SetBackend(aBasePathKvStore string) *db.Backend {
1586 addr := dh.pOpenOnuAc.KVStoreHost + ":" + strconv.Itoa(dh.pOpenOnuAc.KVStorePort)
1587 logger.Debugw("SetKVStoreBackend", log.Fields{"IpTarget": addr,
divyadesai4d299552020-08-18 07:13:49 +00001588 "BasePathKvStore": aBasePathKvStore, "device-id": dh.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +00001589 kvbackend := &db.Backend{
1590 Client: dh.pOpenOnuAc.kvClient,
1591 StoreType: dh.pOpenOnuAc.KVStoreType,
1592 /* address config update acc. to [VOL-2736] */
1593 Address: addr,
1594 Timeout: dh.pOpenOnuAc.KVStoreTimeout,
1595 PathPrefix: aBasePathKvStore}
Holger Hildebrandtc54939a2020-06-17 08:14:27 +00001596
mpagenkoaf801632020-07-03 10:00:42 +00001597 return kvbackend
Holger Hildebrandt24d51952020-05-04 14:03:42 +00001598}
mpagenkodff5dda2020-08-28 11:52:01 +00001599
1600//addFlowItemToUniPort parses the actual flow item to add it to the UniPort
1601func (dh *DeviceHandler) addFlowItemToUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *OnuUniPort) error {
1602 var loSetVlan uint16 = uint16(of.OfpVlanId_OFPVID_NONE) //noValidEntry
1603 var loMatchVlan uint16 = uint16(of.OfpVlanId_OFPVID_PRESENT) //reserved VLANID entry
1604 var loAddPcp, loSetPcp uint8
1605 /* the TechProfileId is part of the flow Metadata - compare also comment within
1606 * OLT-Adapter:openolt_flowmgr.go
1607 * Metadata 8 bytes:
1608 * Most Significant 2 Bytes = Inner VLAN
1609 * Next 2 Bytes = Tech Profile ID(TPID)
1610 * Least Significant 4 Bytes = Port ID
1611 * Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1612 * subscriber related flows.
1613 */
1614
1615 metadata := flow.GetMetadataFromWriteMetadataAction(apFlowItem)
1616 if metadata == 0 {
1617 logger.Debugw("FlowAdd invalid metadata - abort",
1618 log.Fields{"device-id": dh.deviceID})
1619 return errors.New("FlowAdd invalid metadata")
1620 }
1621 loTpID := flow.GetTechProfileIDFromWriteMetaData(metadata)
1622 logger.Debugw("FlowAdd TechProfileId", log.Fields{"device-id": dh.deviceID, "TP-Id": loTpID})
1623 for _, field := range flow.GetOfbFields(apFlowItem) {
1624 switch field.Type {
1625 case of.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
1626 {
1627 logger.Debugw("FlowAdd type EthType", log.Fields{"device-id": dh.deviceID,
1628 "EthType": strconv.FormatInt(int64(field.GetEthType()), 16)})
1629 }
1630 case of.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
1631 {
1632 loIPProto := field.GetIpProto()
1633 logger.Debugw("FlowAdd type IpProto", log.Fields{"device-id": dh.deviceID,
1634 "IpProto": strconv.FormatInt(int64(loIPProto), 16)})
1635 if loIPProto == 2 {
1636 // some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
1637 // avoids installing invalid EVTOCD rule
1638 logger.Debugw("FlowAdd type IpProto 2: TT workaround: ignore flow",
1639 log.Fields{"device-id": dh.deviceID,
1640 "IpProto": strconv.FormatInt(int64(loIPProto), 16)})
1641 return nil
1642 }
1643 }
1644 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
1645 {
1646 loMatchVlan = uint16(field.GetVlanVid())
1647 loMatchVlanMask := uint16(field.GetVlanVidMask())
1648 if !(loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) &&
1649 loMatchVlanMask == uint16(of.OfpVlanId_OFPVID_PRESENT)) {
1650 loMatchVlan = loMatchVlan & 0xFFF // not transparent: copy only ID bits
1651 }
1652 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1653 "VID": strconv.FormatInt(int64(loMatchVlan), 16)})
1654 }
1655 case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
1656 {
1657 loAddPcp = uint8(field.GetVlanPcp())
1658 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1659 "PCP": loAddPcp})
1660 }
1661 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
1662 {
1663 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1664 "UDP-DST": strconv.FormatInt(int64(field.GetUdpDst()), 16)})
1665 }
1666 case of.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
1667 {
1668 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1669 "UDP-SRC": strconv.FormatInt(int64(field.GetUdpSrc()), 16)})
1670 }
1671 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
1672 {
1673 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1674 "IPv4-DST": field.GetIpv4Dst()})
1675 }
1676 case of.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC:
1677 {
1678 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1679 "IPv4-SRC": field.GetIpv4Src()})
1680 }
1681 case of.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
1682 {
1683 logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
1684 "Metadata": field.GetTableMetadata()})
1685 }
1686 /*
1687 default:
1688 {
1689 //all other entires ignored
1690 }
1691 */
1692 }
1693 } //for all OfbFields
1694
1695 for _, action := range flow.GetActions(apFlowItem) {
1696 switch action.Type {
1697 /* not used:
1698 case of.OfpActionType_OFPAT_OUTPUT:
1699 {
1700 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1701 "Output": action.GetOutput()})
1702 }
1703 */
1704 case of.OfpActionType_OFPAT_PUSH_VLAN:
1705 {
1706 logger.Debugw("FlowAdd action type", log.Fields{"device-id": dh.deviceID,
1707 "PushEthType": strconv.FormatInt(int64(action.GetPush().Ethertype), 16)})
1708 }
1709 case of.OfpActionType_OFPAT_SET_FIELD:
1710 {
1711 pActionSetField := action.GetSetField()
1712 if pActionSetField.Field.OxmClass != of.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1713 logger.Warnw("FlowAdd action SetField invalid OxmClass (ignored)", log.Fields{"device-id": dh.deviceID,
1714 "OxcmClass": pActionSetField.Field.OxmClass})
1715 }
1716 if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1717 loSetVlan = uint16(pActionSetField.Field.GetOfbField().GetVlanVid())
1718 logger.Debugw("FlowAdd Set VLAN from SetField action", log.Fields{"device-id": dh.deviceID,
1719 "SetVlan": strconv.FormatInt(int64(loSetVlan), 16)})
1720 } else if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
1721 loSetPcp = uint8(pActionSetField.Field.GetOfbField().GetVlanPcp())
1722 logger.Debugw("FlowAdd Set PCP from SetField action", log.Fields{"device-id": dh.deviceID,
1723 "SetPcp": loSetPcp})
1724 } else {
1725 logger.Warnw("FlowAdd action SetField invalid FieldType", log.Fields{"device-id": dh.deviceID,
1726 "Type": pActionSetField.Field.GetOfbField().Type})
1727 }
1728 }
1729 /*
1730 default:
1731 {
1732 //all other entires ignored
1733 }
1734 */
1735 }
1736 } //for all Actions
1737
1738 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1739 logger.Errorw("FlowAdd aborted - SetVlanId undefined, but MatchVid set", log.Fields{
1740 "device-id": dh.deviceID, "UniPort": apUniPort.portNo,
1741 "set_vid": strconv.FormatInt(int64(loSetVlan), 16),
1742 "match_vid": strconv.FormatInt(int64(loMatchVlan), 16)})
1743 //TODO!!: Use DeviceId within the error response to rwCore
1744 // likewise also in other error response cases to calling components as requested in [VOL-3458]
1745 return errors.New("FlowAdd Set/Match VlanId inconsistent")
1746 }
1747 if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) {
1748 logger.Debugw("FlowAdd vlan-any/copy", log.Fields{"device-id": dh.deviceID})
1749 loSetVlan = loMatchVlan //both 'transparent' (copy any)
1750 } else {
1751 //looks like OMCI value 4097 (copyFromOuter - for Uni double tagged) is not supported here
1752 if loSetVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
1753 // not set to transparent
1754 loSetVlan &= 0x0FFF //mask VID bits as prerequiste for vlanConfigFsm
1755 }
1756 logger.Debugw("FlowAdd vlan-set", log.Fields{"device-id": dh.deviceID})
1757 }
1758 //TODO!!: further FlowAdd requests may be valid even in case the FSM is already running,
1759 // e.g. for multi-step flow configuration, error treatment must be redefined in this context as requested in [VOL-3441]
1760 if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniId]; exist {
1761 logger.Errorw("FlowAdd aborted - FSM already running", log.Fields{
1762 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
1763 return errors.New("FlowAdd FSM already running")
1764 }
1765 return dh.createVlanFilterFsm(apUniPort,
1766 loTpID, loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterDone)
1767}
1768
1769// createVlanFilterFsm initialises and runs the VlanFilter FSM to transfer OMCI related VLAN config
1770func (dh *DeviceHandler) createVlanFilterFsm(apUniPort *OnuUniPort,
1771 aTpID uint16, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8, aDevEvent OnuDeviceEvent) error {
1772 chVlanFilterFsm := make(chan Message, 2048)
1773
1774 pDevEntry := dh.GetOnuDeviceEntry(true)
1775 if pDevEntry == nil {
1776 logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
1777 return fmt.Errorf("No valid OnuDevice for device-id %x - aborting", dh.deviceID)
1778 }
1779
1780 pVlanFilterFsm := NewUniVlanConfigFsm(dh, pDevEntry.PDevOmciCC, apUniPort, dh.pOnuTP,
1781 pDevEntry.pOnuDB, aTpID, aDevEvent, "UniVlanConfigFsm", dh.deviceID, chVlanFilterFsm,
1782 dh.pOpenOnuAc.AcceptIncrementalEvto, aMatchVlan, aSetVlan, aSetPcp)
1783 if pVlanFilterFsm != nil {
1784 dh.UniVlanConfigFsmMap[apUniPort.uniId] = pVlanFilterFsm
1785 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1786 if pVlanFilterStatemachine != nil {
1787 if pVlanFilterStatemachine.Is(vlanStDisabled) {
1788 if err := pVlanFilterStatemachine.Event(vlanEvStart); err != nil {
1789 logger.Warnw("UniVlanConfigFsm: can't start", log.Fields{"err": err})
1790 return fmt.Errorf("Can't start UniVlanConfigFsm for device-id %x", dh.deviceID)
1791 } else {
1792 /***** UniVlanConfigFsm started */
1793 logger.Debugw("UniVlanConfigFsm started", log.Fields{
1794 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
1795 "UniPort": apUniPort.portNo})
1796 }
1797 } else {
1798 logger.Warnw("wrong state of UniVlanConfigFsm - want: disabled", log.Fields{
1799 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
1800 return fmt.Errorf("UniVlanConfigFsm not in expected disabled state for device-id %x", dh.deviceID)
1801 }
1802 } else {
1803 logger.Errorw("UniVlanConfigFsm StateMachine invalid - cannot be executed!!", log.Fields{
1804 "device-id": dh.deviceID})
1805 return fmt.Errorf("UniVlanConfigFsm invalid for device-id %x", dh.deviceID)
1806 }
1807 } else {
1808 logger.Errorw("UniVlanConfigFsm could not be created - abort!!", log.Fields{
1809 "device-id": dh.deviceID, "UniPort": apUniPort.portNo})
1810 return fmt.Errorf("UniVlanConfigFsm could not be created for device-id %x", dh.deviceID)
1811 }
1812 return nil
1813}
1814
1815//verifyUniVlanConfigRequest checks on existence of flow configuration and starts it accordingly
1816func (dh *DeviceHandler) verifyUniVlanConfigRequest(apUniPort *OnuUniPort) {
1817 //TODO!! verify and start pending flow configuration
1818 //some pending config request my exist in case the UniVlanConfig FSM was already started - with internal data -
1819 //but execution was set to 'on hold' as first the TechProfile config had to be applied
1820 if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[apUniPort.uniId]; exist {
1821 //VlanFilterFsm exists and was already started (assumed to wait for TechProfile execution here)
1822 pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
1823 if pVlanFilterStatemachine != nil {
1824 if pVlanFilterStatemachine.Is(vlanStWaitingTechProf) {
1825 if err := pVlanFilterStatemachine.Event(vlanEvContinueConfig); err != nil {
1826 logger.Warnw("UniVlanConfigFsm: can't continue processing", log.Fields{"err": err})
1827 } else {
1828 /***** UniVlanConfigFsm continued */
1829 logger.Debugw("UniVlanConfigFsm continued", log.Fields{
1830 "state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
1831 "UniPort": apUniPort.portNo})
1832 }
1833 } else {
1834 logger.Debugw("no state of UniVlanConfigFsm to be continued", log.Fields{
1835 "have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
1836 }
1837 } else {
1838 logger.Debugw("UniVlanConfigFsm StateMachine does not exist, no flow processing", log.Fields{
1839 "device-id": dh.deviceID})
1840 }
1841
1842 } // else: nothing to do
1843}
1844
1845//RemoveVlanFilterFsm deletes the stored pointer to the VlanConfigFsm
1846// intention is to provide this method to be called from VlanConfigFsm itself, when resources (and methods!) are cleaned up
1847func (dh *DeviceHandler) RemoveVlanFilterFsm(apUniPort *OnuUniPort) {
1848 logger.Debugw("remove UniVlanConfigFsm StateMachine", log.Fields{
1849 "device-id": dh.deviceID, "uniPort": apUniPort.portNo})
1850 //save to do, even if entry dows not exist
1851 delete(dh.UniVlanConfigFsmMap, apUniPort.uniId)
1852}