blob: 3eb3a084091ec79be77be6c36e1b5861a30090c3 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
Joey Armstronga6af1522023-01-17 16:06:16 -05002 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
Phaneendra Manda4c62c802019-03-06 21:37:49 +05303
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 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Mahir Gunyela2e68702022-12-07 00:00:42 -080017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040042 "github.com/opencord/voltha-lib-go/v7/pkg/config"
43 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
44 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
45 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070046 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080048
khenaidoo106c61a2021-08-11 18:05:46 -040049 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053050 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080051 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040053 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
56 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040057 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
58 oop "github.com/opencord/voltha-protos/v5/go/openolt"
59 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070060 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040061 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053063)
64
salmansiddiqui7ac62132019-08-22 03:58:50 +000065// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040066const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080067 InvalidPort = 0xffffffff
68 MaxNumOfGroupHandlerChannels = 256
69
70 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
71 McastFlowOrGroupModify = "McastFlowOrGroupModify"
72 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050073 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010074
75 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053076 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040077)
78
Mahir Gunyela2e68702022-12-07 00:00:42 -080079// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053080type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040081 cm *config.ConfigManager
82 device *voltha.Device
83 cfg *conf.AdapterFlags
84 coreClient *vgrpc.Client
85 childAdapterClients map[string]*vgrpc.Client
86 lockChildAdapterClients sync.RWMutex
87 EventProxy eventif.EventProxy
88 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050089 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040090 lockDevice sync.RWMutex
91 Client oop.OpenoltClient
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 flowMgr []*OpenOltFlowMgr
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053098 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070099
100 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530101
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700102 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
103 // if the value is true that means the OnuDiscovery indication
104 // is currently being processed and thus we can ignore concurrent requests
105 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
106 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700107 discOnus sync.Map
108 onus sync.Map
109 portStats *OpenOltStatisticsMgr
110 metrics *pmmetrics.PmMetrics
111 stopCollector chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000112 isCollectorActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700113 stopHeartbeatCheck chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000114 isHeartbeatCheckActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700115 activePorts sync.Map
116 stopIndications chan bool
117 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700118
Mahir Gunyelb0046752021-02-26 13:51:05 -0800119 totalPonPorts uint32
120 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
121 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800122
123 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
124 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700125 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
126 stopMcastHandlerRoutine []chan bool
127 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000128
129 adapterPreviouslyConnected bool
130 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700131
132 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530133 heartbeatSignature uint32
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134}
135
Mahir Gunyela2e68702022-12-07 00:00:42 -0800136// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400138 deviceID string
139 deviceType string
140 serialNumber string
141 onuID uint32
142 intfID uint32
143 proxyDeviceID string
144 losRaised bool
145 rdiRaised bool
146 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700147}
148
Mahir Gunyelb0046752021-02-26 13:51:05 -0800149type onuIndicationMsg struct {
150 ctx context.Context
151 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800152}
153
154type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800155 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800156 stopChannel chan struct{}
157}
158
Mahir Gunyela2e68702022-12-07 00:00:42 -0800159// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
160// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
161// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
162// and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800163type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400164 ctx context.Context // Flow/group handler context
165 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
166 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
167 group *of.OfpGroupEntry // Group message (can be nil or valid group)
168 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800169}
170
Naga Manjunath7615e552019-10-11 22:35:47 +0530171var pmNames = []string{
172 "rx_bytes",
173 "rx_packets",
174 "rx_mcast_packets",
175 "rx_bcast_packets",
176 "tx_bytes",
177 "tx_packets",
178 "tx_mcast_packets",
179 "tx_bcast_packets",
180}
181
Mahir Gunyela2e68702022-12-07 00:00:42 -0800182// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400183func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700184 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700186 device.deviceType = deviceTp
187 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700188 device.onuID = onuID
189 device.intfID = intfID
190 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530191 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400192 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700193 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530194}
195
Mahir Gunyela2e68702022-12-07 00:00:42 -0800196// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400197func NewDeviceHandler(cc *vgrpc.Client, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager, cfg *conf.AdapterFlags) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700198 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530199 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800200 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400201 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400202 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 dh.device = cloned
205 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500206 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700207 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000208 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
209 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530210 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500211 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800212 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800213 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400214 dh.childAdapterClients = make(map[string]*vgrpc.Client)
215 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300216 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530217 if dh.kvStore == nil {
218 logger.Error(ctx, "Failed to setup KV store")
219 return nil
220 }
221
Girish Gowdra491a9c62021-01-06 16:43:07 -0800222 // Create a slice of buffered channels for handling concurrent mcast flow/group.
223 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700224 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
225 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800226 for i := range dh.incomingMcastFlowOrGroup {
227 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800228 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800229 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
230 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
231 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
232 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700233 dh.mcastHandlerRoutineActive[i] = true
234 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800235 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700236 //TODO initialize the support classes.
237 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530238}
239
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530240func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
241 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
242 switch storeType {
243 case "etcd":
244 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
245 }
246 return nil, errors.New("unsupported-kv-store")
247}
248
249// SetKVClient sets the KV client and return a kv backend
250func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
251 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
252 if err != nil {
253 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
254 return nil
255 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530256 kvbackend := &db.Backend{
257 Client: kvClient,
258 StoreType: backend,
259 Address: addr,
260 Timeout: rsrcMgr.KvstoreTimeout,
261 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
262
263 return kvbackend
264}
265
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000266// CloseKVClient closes open KV clients
267func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
268 if dh.resourceMgr != nil {
269 for _, rscMgr := range dh.resourceMgr {
270 if rscMgr != nil {
271 rscMgr.CloseKVClient(ctx)
272 }
273 }
274 }
275 if dh.flowMgr != nil {
276 for _, flMgr := range dh.flowMgr {
277 if flMgr != nil {
278 flMgr.CloseKVClient(ctx)
279 }
280 }
281 }
282}
283
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530284// start save the device to the data model
285func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 dh.lockDevice.Lock()
287 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000288 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700289 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000290 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530291}
292
khenaidooefff76e2021-12-15 16:51:30 -0500293// Stop stops the device handler
294func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 dh.lockDevice.Lock()
296 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000297 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500298 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400299
khenaidooefff76e2021-12-15 16:51:30 -0500300 // Delete (which will stop also) all grpc connections to the child adapters
301 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000302 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530303}
304
ssiddiqui04386ee2021-08-23 21:58:25 +0530305func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
306 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
307 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
308 if pooledIntfID == intfID {
309 return resourceRanges.GetTechnology()
310 }
311 }
312 }
313 return ""
314}
315
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400316func macifyIP(ip net.IP) string {
317 if len(ip) > 0 {
318 oct1 := strconv.FormatInt(int64(ip[12]), 16)
319 oct2 := strconv.FormatInt(int64(ip[13]), 16)
320 oct3 := strconv.FormatInt(int64(ip[14]), 16)
321 oct4 := strconv.FormatInt(int64(ip[15]), 16)
322 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
323 }
324 return ""
325}
326
Neha Sharma96b7bf22020-06-15 10:37:32 +0000327func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400328 var genmac string
329 var addr net.IP
330 var ips []string
331 var err error
332
Neha Sharma96b7bf22020-06-15 10:37:32 +0000333 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400334
335 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400337
338 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000339 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400340 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000341 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400342 }
343 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000344 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530345 log.Fields{"host": ips[0],
346 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400347 return genmac, nil
348 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000349 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400350 }
351
352 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000353 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530354 log.Fields{"host": host,
355 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400356 return genmac, nil
357}
358
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530359func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700360 slist := strings.Split(mac, ":")
361 result := make([]uint32, len(slist))
362 var err error
363 var tmp int64
364 for index, val := range slist {
365 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
366 return []uint32{1, 2, 3, 4, 5, 6}
367 }
368 result[index] = uint32(tmp)
369 }
370 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530371}
372
Mahir Gunyela2e68702022-12-07 00:00:42 -0800373// GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800374func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530375
David K. Bainbridge794735f2020-02-11 21:01:37 -0800376 switch portType {
377 case voltha.Port_ETHERNET_NNI:
378 return fmt.Sprintf("nni-%d", portNum), nil
379 case voltha.Port_PON_OLT:
380 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700381 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382
Girish Kumarf26e4882020-03-05 06:49:10 +0000383 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530384}
385
Elia Battiston596406d2022-02-02 12:19:00 +0100386func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
387 if speedMbps == 0 {
388 //In case it was not set in the indication
389 //and no other value was provided
390 speedMbps = defaultPortSpeedMbps
391 }
392
393 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
394 switch speedMbps {
395 case 1000000:
396 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
397 case 100000:
398 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
399 case 40000:
400 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
401 case 10000:
402 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
403 case 1000:
404 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
405 case 100:
406 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
407 case 10:
408 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
409 }
410
411 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
412
413 port := &of.OfpPort{
414 HwAddr: macAddressToUint32Array(macAddress),
415 Config: 0,
416 State: uint32(of.OfpPortState_OFPPS_LIVE),
417 Curr: capacity,
418 Advertised: capacity,
419 Peer: capacity,
420 CurrSpeed: speedMbps * 1000, //kbps
421 MaxSpeed: speedMbps * 1000, //kbps
422 }
423
424 return port
425}
426
427func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000428 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700429 if state == "up" {
430 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500431 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500432 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700433 } else {
434 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500435 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700436 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700437 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400438 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800439 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000440 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400441 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500442
khenaidoo106c61a2021-08-11 18:05:46 -0400443 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400444 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400445 DeviceId: dh.device.Id,
446 Port: portNum,
447 })
448 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000449 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400450 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400451 DeviceId: dh.device.Id,
452 PortType: portType,
453 PortNo: portNum,
454 OperStatus: operStatus})
455 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400456 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
457 "device-id": dh.device.Id,
458 "port-type": portType,
459 "port-number": portNum,
460 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500461 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400462 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500463 }
khenaidoo106c61a2021-08-11 18:05:46 -0400464
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400465 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400466 port = &voltha.Port{
467 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700468 PortNo: portNum,
469 Label: label,
470 Type: portType,
471 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100472 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700473 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000474 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700475 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400476 err = dh.createPortInCore(ctx, port)
477 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000478 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800479 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000480 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400481 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000482 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530483 return nil
484}
485
Kent Hagermane6ff1012020-07-14 15:07:53 -0400486func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400487 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530488 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400489 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
490 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530491 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800492 dh.lockDevice.Lock()
493 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530494 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530495}
496
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700497// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530498// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800499func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000500 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700501 defer func() {
502 dh.lockDevice.Lock()
503 dh.isReadIndicationRoutineActive = false
504 dh.lockDevice.Unlock()
505 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700506 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700507 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700508 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700509 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400510
David Bainbridgef5879ca2019-12-13 21:17:54 +0000511 // Create an exponential backoff around re-enabling indications. The
512 // maximum elapsed time for the back off is set to 0 so that we will
513 // continue to retry. The max interval defaults to 1m, but is set
514 // here for code clarity
515 indicationBackoff := backoff.NewExponentialBackOff()
516 indicationBackoff.MaxElapsedTime = 0
517 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700518
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700519 dh.lockDevice.Lock()
520 dh.isReadIndicationRoutineActive = true
521 dh.lockDevice.Unlock()
522
Girish Gowdra3f974912020-03-23 20:35:18 -0700523Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700524 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400525 select {
526 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000527 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700528 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400529 default:
530 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100531
532 select {
533 case <-indications.Context().Done():
534 if err != nil {
535 logger.Warnw(ctx, "error-during-enable-indications",
536 log.Fields{"err": err,
537 "device-id": dh.device.Id})
538 }
539
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400540 // Use an exponential back off to prevent getting into a tight loop
541 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100542 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
543 "device-id": dh.device.Id,
544 "duration": duration,
545 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400546 if duration == backoff.Stop {
547 // If we reach a maximum then warn and reset the backoff
548 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100549 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530550 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530551 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400552 indicationBackoff.Reset()
553 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700554
555 // On failure process a backoff timer while watching for stopIndications
556 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700557 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700558 select {
559 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000560 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700561 if !backoffTimer.Stop() {
562 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700563 }
564 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700565 case <-backoffTimer.C:
566 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700567 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700568 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
569 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400570 }
571 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100572 default:
573 if err != nil {
574 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530575 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530576 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100577 // Close the stream, and re-initialize it
578 if err = indications.CloseSend(); err != nil {
579 // Ok to ignore here, because we landed here due to a problem on the stream
580 // In all probability, the closeSend call may fail
581 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
582 log.Fields{"err": err,
583 "device-id": dh.device.Id})
584 }
585 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
586 return err
587 }
588 // once we re-initialized the indication stream, continue to read indications
589 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700590 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100591 // Reset backoff if we have a successful receive
592 indicationBackoff.Reset()
593 // When OLT is admin down, ignore all indications.
594 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
595 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
596 log.Fields{"indication": indication,
597 "device-id": dh.device.Id})
598 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700599 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100600 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530601 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700602 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700604 // Close the send stream
605 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700606
Girish Gowdra3f974912020-03-23 20:35:18 -0700607 return nil
608}
609
610func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700611 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700612 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
613 if err != nil {
614 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
615 }
616 if indications == nil {
617 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
618 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700619 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700620 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400621}
622
623// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
624func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
625 switch indication.Data.(type) {
626 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
627 return true
628
629 default:
630 return false
631 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632}
633
David K. Bainbridge794735f2020-02-11 21:01:37 -0800634func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700635 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000636 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530637 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530639 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000641 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000642 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530643 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000644 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800645 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000646 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800647 }
648 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649}
650
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530652func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700653 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654 switch indication.Data.(type) {
655 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000656 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
657 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700658 logger.Infow(ctx, "received olt indication", log.Fields{"device-id": dh.device.Id, "olt-ind": indication.GetOltInd()})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800659 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400660 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800661 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000663 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
664 defer span.Finish()
665
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100668 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400669 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800670 }
671 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000672 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000674 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
675 defer span.Finish()
676
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 intfOperInd := indication.GetIntfOperInd()
678 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100680 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400681 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800682 }
683 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700684 } else if intfOperInd.GetType() == "pon" {
685 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
686 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800687 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100688 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400689 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 }
691 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000692 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000694 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530695 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530696 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000698 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
699 defer span.Finish()
700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800703 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800704 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000706 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
707 defer span.Finish()
708
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000710 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800711 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800712 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000714 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
715 defer span.Finish()
716
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700717 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000718 logger.Debugw(ctx, "received-omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800719 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000720 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400721 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800722 }
723 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000725 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
726 defer span.Finish()
727
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000729 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700730 "intf-type": pktInd.IntfId,
731 "intf-id": pktInd.IntfId,
732 "gem-port-id": pktInd.GemportId,
733 "port-no": pktInd.PortNo,
734 "device-id": dh.device.Id,
735 })
736
737 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000738 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700739 "intf-type": pktInd.IntfId,
740 "intf-id": pktInd.IntfId,
741 "gem-port-id": pktInd.GemportId,
742 "port-no": pktInd.PortNo,
743 "packet": hex.EncodeToString(pktInd.Pkt),
744 "device-id": dh.device.Id,
745 })
746 }
747
David K. Bainbridge794735f2020-02-11 21:01:37 -0800748 go func() {
749 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400750 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800751 }
752 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700753 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000754 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
755 defer span.Finish()
756
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700757 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700758 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000760 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
761 defer span.Finish()
762
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000764 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700765 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000766 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
767 defer span.Finish()
768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000770 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
771 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700772 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530773}
774
nikesh.krishnanc8473432023-06-14 12:14:54 +0530775func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
776 onuInd := &oop.OnuIndication{
777 IntfId: intfID,
778 OnuId: onuID,
779 OperState: operState,
780 AdminState: adminState,
781 }
782 indication := &oop.Indication{
783 Data: &oop.Indication_OnuInd{
784 OnuInd: onuInd,
785 },
786 }
787 return indication
788}
789
790func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
791 onuAlarmInd := &oop.OnuAlarmIndication{
792 IntfId: intfID,
793 OnuId: onuID,
794 LosStatus: losStatus,
795 }
796 alarmInd := &oop.AlarmIndication{
797 Data: &oop.AlarmIndication_OnuAlarmInd{
798 OnuAlarmInd: onuAlarmInd,
799 },
800 }
801 return alarmInd
802}
803func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
804
805 ponlosAlarmInd := &oop.LosIndication{
806 IntfId: intfID,
807 Status: losStatus,
808 }
809 alarmInd := &oop.AlarmIndication{
810 Data: &oop.AlarmIndication_LosInd{
811 LosInd: ponlosAlarmInd,
812 },
813 }
814 return alarmInd
815}
816func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
817 go func() {
818 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
819 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
820 }
821 }()
822
823 raisedTs := time.Now().Unix()
824 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
825}
826
827func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
828
829 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
830 if err != nil {
831
832 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
833
834 return err
835 }
836 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
837
838 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
839 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
840 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
841
842 onuID := onuDeviceFromCore.ProxyAddress.OnuId
843 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
844 if err != nil {
845 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
846
847 } else {
848 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
849 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
850 switch {
851 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
852 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
853 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
854
855 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
856 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") //check bal cli login notepad
857 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
858 raisedTs := time.Now().Unix()
859 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
860
861 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
862 }
863
864 }
865
866 }
867
868 return nil
869}
870
871func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
872 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
873 DeviceId: dh.device.Id,
874 PortType: voltha.Port_PON_OLT,
875 })
876 if err != nil {
877 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
878
879 return err
880
881 }
882 for _, portFromCore := range portsFromCore.Items {
883 portNum := portFromCore.GetPortNo()
884 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
885 portOperStatusFromCore := portFromCore.OperStatus
886 portAdminStateFromCore := portFromCore.AdminState
887 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
888 if err != nil {
889 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
890 } else {
891 portLosFromOlt := ponPortFromOlt.GetLos()
892 portStateFromOlt := ponPortFromOlt.GetState()
893 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
894 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
895 "portStateFromOlt": portStateFromOlt.String(),
896 "portOperStatusFromCore": portOperStatusFromCore.String(),
897 "device-id": dh.device.Id,
898 "port": portNum})
899 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
900 raisedTs := time.Now().Unix()
901 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
902
903 }
904 switch {
905 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
906 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
907 "portStateFromOlt": portStateFromOlt.String(),
908 "portOperStatusFromCore": portOperStatusFromCore.String(),
909 "device-id": dh.device.Id,
910 "port": portNum})
911 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
912 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
913 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
914 "portStateFromOlt": portStateFromOlt.String(),
915 "portOperStatusFromCore": portOperStatusFromCore.String(),
916 "device-id": dh.device.Id,
917 "port": portNum})
918 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
919 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
920 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
921 "device-id": dh.device.Id,
922 "port": portNum})
923 default:
924 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
925 "portStateFromOlt": portStateFromOlt.String(),
926 "portOperStatusFromCore": portOperStatusFromCore.String(),
927 "device-id": dh.device.Id,
928 "port": portNum})
929
930 }
931
932 }
933
934 }
935
936 return nil
937}
938
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530939// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530940func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530941 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530943 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
944 if err == nil {
945 if device.OperStatus == voltha.OperStatus_RECONCILING {
946 err = dh.reconcileOnus(ctx)
947 if err != nil {
948 logger.Error(ctx, "unable to reconcile onu", log.Fields{"eeror": err})
949 }
950 err = dh.reconcilePonPorts(ctx)
951 if err != nil {
952 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"eeror": err})
953 }
954 }
955 }
Girish Gowdra618fa572021-09-01 17:19:29 -0700956 // instantiate the mcast handler routines.
957 for i := range dh.incomingMcastFlowOrGroup {
958 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
959 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
960 if !dh.mcastHandlerRoutineActive[i] {
961 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
962 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
963 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
964 // for incoming mcast flow/group to be processed serially.
965 dh.mcastHandlerRoutineActive[i] = true
966 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
967 }
968 }
969
Girish Gowdru0c588b22019-04-23 23:24:56 -0400970 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400971 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400972 DeviceId: dh.device.Id,
973 OperStatus: voltha.OperStatus_ACTIVE,
974 ConnStatus: voltha.ConnectStatus_REACHABLE,
975 }); err != nil {
976 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400977 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000978
979 //Clear olt communication failure event
980 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
981 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700982 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000983 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
984
Girish Gowdru0c588b22019-04-23 23:24:56 -0400985 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530986}
987
988// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530989func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000990 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400991
khenaidoo106c61a2021-08-11 18:05:46 -0400992 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400993 if err != nil || device == nil {
994 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000995 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400996 }
997
998 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400999
1000 //Update the device oper state and connection status
1001 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001002 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001003 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001004 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001005
khenaidoodc2116e2021-10-19 17:33:19 -04001006 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001007 DeviceId: cloned.Id,
1008 OperStatus: cloned.OperStatus,
1009 ConnStatus: cloned.ConnectStatus,
1010 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001011 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001012 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001013
1014 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001015 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001016 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001017 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001018 }
1019 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001020 // Update onu state as down in onu adapter
1021 onuInd := oop.OnuIndication{}
1022 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001023
1024 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1025 if err != nil {
1026 return err
1027 }
1028 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001029 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001030 DeviceId: onuDevice.Id,
1031 OnuIndication: &onuInd,
1032 })
1033 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001034 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001035 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001036 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001037 "onu-indicator": onuInd,
1038 "device-type": onuDevice.Type,
1039 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -07001040 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001041 } else {
1042 logger.Debugw(ctx, "sending inter adapter down ind to onu success", log.Fields{"olt-device-id": device.Id, "onu-device-id": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001043 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001044 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001045 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001046 /* Discovered ONUs entries need to be cleared , since after OLT
1047 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301048 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001049 dh.lockDevice.Unlock()
1050
Neha Sharma96b7bf22020-06-15 10:37:32 +00001051 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001052 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301053}
1054
1055// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301056func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001057 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001058
1059 // if the connection is already available, close the previous connection (olt reboot case)
1060 if dh.clientCon != nil {
1061 if err = dh.clientCon.Close(); err != nil {
1062 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1063 } else {
1064 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1065 }
1066 }
1067
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301068 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001069 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001070 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1071 grpc.WithInsecure(),
1072 grpc.WithBlock(),
1073 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001074 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001075 )),
1076 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001077 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001078 )))
1079
1080 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301081 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301082 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001083 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001084 }
1085 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301086}
1087
1088// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301089func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001090 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301091 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001092 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301093}
1094
1095// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301096func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301097 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001098 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001099
1100 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001101 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301102 if err != nil || device == nil {
1103 /*TODO: needs to handle error scenarios */
1104 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1105 }
1106 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001107 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001108
1109 cloned := proto.Clone(device).(*voltha.Device)
1110 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1111 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1112 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001113
khenaidoodc2116e2021-10-19 17:33:19 -04001114 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001115 DeviceId: cloned.Id,
1116 OperStatus: cloned.OperStatus,
1117 ConnStatus: cloned.ConnectStatus,
1118 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301119 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001120 }
1121
Chaitrashree G S44124192019-08-07 20:21:36 -04001122 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
npujarec5762e2020-01-01 14:08:48 +05301123 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001124 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301125 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001126 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001127 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1128 // all the modules initialized and ready to handle incoming ONUs.
1129
Thomas Lee S985938d2020-05-04 11:40:41 +05301130 err = dh.initializeDeviceHandlerModules(ctx)
1131 if err != nil {
1132 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001133 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001134
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001135 go startHeartbeatCheck(ctx, dh)
1136
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001137 return nil
1138 }
1139
khenaidoo106c61a2021-08-11 18:05:46 -04001140 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001141 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -04001142 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001143 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001144 }
khenaidoo106c61a2021-08-11 18:05:46 -04001145 dh.populateActivePorts(ctx, ports.Items)
1146 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001147 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001148 }
1149
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001150 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301151 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001152 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301153
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001155
1156 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001157 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001158 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001159
1160 go startHeartbeatCheck(ctx, dh)
1161
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301163}
1164
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001165func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001166 var err error
1167 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001168
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001169 if dh.flowMgr != nil {
1170 dh.StopAllFlowRoutines(ctx)
1171 }
1172
1173 dh.CloseKVClient(ctx)
1174
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001175 if err != nil {
1176 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1177 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001178 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1179 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001180 // +1 is for NNI
1181 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1182 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001183 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001184 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1185 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1186 // There is only one NNI manager since multiple NNI is not supported for now
1187 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001188 // Instantiate resource manager
1189 if dh.resourceMgr[i] = rsrcMgr.NewResourceMgr(ctx, i, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, dh.deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07001190 return olterrors.ErrResourceManagerInstantiating
1191 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001192 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001193 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1194 // the KV store to manage mcast group data. Provide the first instance (0th index)
1195 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1196 return olterrors.ErrGroupManagerInstantiating
1197 }
yasin saplid0566272021-12-21 09:10:30 +00001198 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001199 // Instantiate flow manager
1200 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001201 //Continue to check the rest of the ports
1202 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1203 } else {
1204 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001205 }
1206 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001207 /* TODO: Instantiate Alarm , stats , BW managers */
1208 /* Instantiating Event Manager to handle Alarms and KPIs */
1209 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1210
1211 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001212 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001213
1214 return nil
1215
1216}
1217
Neha Sharma96b7bf22020-06-15 10:37:32 +00001218func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001219 var err error
1220 var deviceInfo *oop.DeviceInfo
1221
Neha Sharma8f4e4322020-08-06 10:51:53 +00001222 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001223
1224 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001225 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001226 }
1227 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001228 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001229 }
1230
Neha Sharma96b7bf22020-06-15 10:37:32 +00001231 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001232 dh.device.Root = true
1233 dh.device.Vendor = deviceInfo.Vendor
1234 dh.device.Model = deviceInfo.Model
1235 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1236 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1237 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1238
1239 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001241 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001242 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001243 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001244 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001245 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001246 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001247 dh.device.MacAddress = genmac
1248 } else {
1249 dh.device.MacAddress = deviceInfo.DeviceId
1250 }
1251
1252 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001253 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001254 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001255 }
1256
1257 return deviceInfo, nil
1258}
1259
Neha Sharma96b7bf22020-06-15 10:37:32 +00001260func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001261 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001262
1263 defer func() {
1264 dh.lockDevice.Lock()
1265 dh.isCollectorActive = false
1266 dh.lockDevice.Unlock()
1267 }()
1268
1269 dh.lockDevice.Lock()
1270 dh.isCollectorActive = true
1271 dh.lockDevice.Unlock()
1272
Naga Manjunath7615e552019-10-11 22:35:47 +05301273 for {
1274 select {
1275 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001276 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301277 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001278 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001279
khenaidoo106c61a2021-08-11 18:05:46 -04001280 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001281 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001282 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001283 continue
1284 }
khenaidoo106c61a2021-08-11 18:05:46 -04001285 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301286 // NNI Stats
1287 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001288 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301289 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001290 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001291 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001292 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301293 }
1294 // PON Stats
1295 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001296 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301297 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1298 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001299 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001300 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301301 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001302 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001303
yasin sapli9e4c5092022-02-01 13:52:33 +00001304 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001305 if len(onuGemInfoLst) > 0 {
1306 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001307 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001308 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301309 }
1310 }
1311 }
1312}
1313
Mahir Gunyela2e68702022-12-07 00:00:42 -08001314// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301315func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001316 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001317 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301318 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301319
1320 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001321 cgClient, err := dh.coreClient.GetCoreServiceClient()
1322 if err != nil {
1323 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1324 return
1325 }
1326
1327 // Now, set the initial PM configuration for that device
1328 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001329 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301330 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301331}
1332
Mahir Gunyela2e68702022-12-07 00:00:42 -08001333// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001334func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1335 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001336 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301337 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001338 HwDesc: "open_pon",
1339 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001340 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001341 },
1342 SwitchFeatures: &of.OfpSwitchFeatures{
1343 NBuffers: 256,
1344 NTables: 2,
1345 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1346 of.OfpCapabilities_OFPC_TABLE_STATS |
1347 of.OfpCapabilities_OFPC_PORT_STATS |
1348 of.OfpCapabilities_OFPC_GROUP_STATS),
1349 },
1350 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301351}
1352
khenaidoo106c61a2021-08-11 18:05:46 -04001353// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001354func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001355 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001356 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001357 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001358 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001359 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1360 return nil, olterrors.NewErrNotFound("no-flow-manager-found", log.Fields{"intf-id": ifID, "parent-device-id": request.ParentDeviceId, "child-device-id": request.DeviceId}, nil).Log()
1361 }
khenaidoo106c61a2021-08-11 18:05:46 -04001362 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001363
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001364}
1365
Neha Sharma96b7bf22020-06-15 10:37:32 +00001366func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001367 logger.Debugw(ctx, "omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "parent-device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001368 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 var deviceID string
1370 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001371 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001372
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001373 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001374 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "recv-omci-msg", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id,
Matteo Scandolo92186242020-06-12 10:54:18 -07001376 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1377 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001378
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001379 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301380
1381 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1382
Neha Sharma96b7bf22020-06-15 10:37:32 +00001383 logger.Debugw(ctx, "omci-indication-for-a-device-not-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001384 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001385
khenaidoodc2116e2021-10-19 17:33:19 -04001386 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001387 ParentId: dh.device.Id,
1388 OnuId: omciInd.OnuId,
1389 ParentPortNo: ponPort,
1390 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001391 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301392 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001393 "intf-id": omciInd.IntfId,
1394 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001395 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001396 deviceType = onuDevice.Type
1397 deviceID = onuDevice.Id
1398 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001399 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001400 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001401 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001402 } else {
1403 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001404 logger.Debugw(ctx, "omci-indication-for-a-device-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301405 deviceType = onuInCache.(*OnuDevice).deviceType
1406 deviceID = onuInCache.(*OnuDevice).deviceID
1407 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001408 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001409 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001410
khenaidoodc2116e2021-10-19 17:33:19 -04001411 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001412 ParentDeviceId: proxyDeviceID,
1413 ChildDeviceId: deviceID,
1414 Message: omciInd.Pkt,
1415 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301416 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001417 "source": dh.openOLT.config.AdapterEndpoint,
1418 "device-type": deviceType,
1419 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001422 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301424}
1425
khenaidoo106c61a2021-08-11 18:05:46 -04001426// //ProcessInterAdapterMessage sends the proxied messages to the target device
1427// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1428// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001429// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001430// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001431// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001432// return dh.handleInterAdapterOmciMsg(ctx, msg)
1433// }
1434// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1435// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001436
kesavandb9f54fd2021-11-25 20:08:04 +05301437// ProxyOmciRequests sends the proxied OMCI message to the target device
1438func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301439 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1440 return status.Error(codes.Unavailable, "OLT unreachable")
1441 }
kesavandb9f54fd2021-11-25 20:08:04 +05301442 if omciMsgs.GetProxyAddress() == nil {
1443 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1444 if err != nil {
1445 return olterrors.NewErrNotFound("onu", log.Fields{
1446 "parent-device-id": dh.device.Id,
1447 "child-device-id": omciMsgs.ChildDeviceId}, err)
1448 }
1449 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1450 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1451 return olterrors.NewErrCommunication("send-failed", log.Fields{
1452 "parent-device-id": dh.device.Id,
1453 "child-device-id": omciMsgs.ChildDeviceId}, err)
1454 }
1455 } else {
1456 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1457 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1458 return olterrors.NewErrCommunication("send-failed", log.Fields{
1459 "parent-device-id": dh.device.Id,
1460 "child-device-id": omciMsgs.ChildDeviceId}, err)
1461 }
1462 }
1463 return nil
1464}
1465
1466func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1467 var intfID uint32
1468 var onuID uint32
1469 var connectStatus common.ConnectStatus_Types
1470 if onuDevice != nil {
1471 intfID = onuDevice.ProxyAddress.GetChannelId()
1472 onuID = onuDevice.ProxyAddress.GetOnuId()
1473 connectStatus = onuDevice.ConnectStatus
1474 } else {
1475 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1476 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1477 connectStatus = omciMsgs.GetConnectStatus()
1478 }
1479 if connectStatus != voltha.ConnectStatus_REACHABLE {
1480 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1481
1482 return olterrors.NewErrCommunication("unreachable", log.Fields{
1483 "intf-id": intfID,
1484 "onu-id": onuID}, nil)
1485 }
1486
1487 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1488 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1489
1490 onuSecOmciMsgList := omciMsgs.GetMessages()
1491
1492 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1493
1494 var omciMessage *oop.OmciMsg
1495 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1496 hex.Encode(hexPkt, onuSecOmciMsg)
1497 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1498
1499 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1500 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1501 //https://jira.opencord.org/browse/VOL-4604
1502 transid := extractOmciTransactionID(onuSecOmciMsg)
1503 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1504 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1505
1506 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1507 if err != nil {
1508 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1509 "intf-id": intfID,
1510 "onu-id": onuID,
1511 "message": omciMessage}, err)
1512 }
1513 }
1514 return nil
1515}
1516
khenaidoo106c61a2021-08-11 18:05:46 -04001517// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001518func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001519 logger.Debugw(ctx, "proxy-omci-message", log.Fields{"parent-device-id": omciMsg.ParentDeviceId, "child-device-id": omciMsg.ChildDeviceId, "proxy-address": omciMsg.ProxyAddress, "connect-status": omciMsg.ConnectStatus})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001520
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301521 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1522 return status.Error(codes.Unavailable, "OLT unreachable")
1523 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001524 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001525 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001526 if err != nil {
1527 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001528 "parent-device-id": dh.device.Id,
1529 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001530 }
khenaidoo106c61a2021-08-11 18:05:46 -04001531 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1532 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001533 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001534 "parent-device-id": dh.device.Id,
1535 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001536 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001537 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001538 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1539 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001540 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001541 "parent-device-id": dh.device.Id,
1542 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001543 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001544 }
1545 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301546}
1547
khenaidoodc2116e2021-10-19 17:33:19 -04001548func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001549 var intfID uint32
1550 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001551 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001552 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553 intfID = onuDevice.ProxyAddress.GetChannelId()
1554 onuID = onuDevice.ProxyAddress.GetOnuId()
1555 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001556 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001557 intfID = omciMsg.GetProxyAddress().GetChannelId()
1558 onuID = omciMsg.GetProxyAddress().GetOnuId()
1559 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001560 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001561 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001563
Thomas Lee S94109f12020-03-03 16:39:29 +05301564 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001565 "intf-id": intfID,
1566 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001567 }
1568
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001569 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1570 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301571 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001572 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001573 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1574 hex.Encode(hexPkt, omciMsg.Message)
1575 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1576
1577 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1578 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1579 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001580 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001581 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001582
Neha Sharma8f4e4322020-08-06 10:51:53 +00001583 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001584 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301585 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001586 "intf-id": intfID,
1587 "onu-id": onuID,
1588 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001589 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001590 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001591}
1592
David K. Bainbridge794735f2020-02-11 21:01:37 -08001593func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301594 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id, "OmccEncryption": dh.openOLT.config.OmccEncryption})
yasin saplibddc2d72022-02-08 13:10:17 +00001595 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001596 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001597 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001598 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301599 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301600 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001601 st, _ := status.FromError(err)
1602 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001603 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1604
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001605 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301606 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001607 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001608 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001609 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001610 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001611 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001612}
1613
Mahir Gunyela2e68702022-12-07 00:00:42 -08001614// getChildDevice function can be used in general to get child device, if not found in cache the function will
1615// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301616func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1617 var InCacheOnuDev *OnuDevice
1618 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1619 if onuInCache.(*OnuDevice).serialNumber == sn {
1620 InCacheOnuDev = onuInCache.(*OnuDevice)
1621 return false
1622 }
1623 return true
1624 })
1625 //Got the onu device from cache return
1626 if InCacheOnuDev != nil {
1627 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1628 return InCacheOnuDev
1629 }
1630 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1631 ParentId: dh.device.Id,
1632 SerialNumber: sn,
1633 ParentPortNo: parentPortNo,
1634 })
1635 //No device found in core return nil
1636 if onuDevice == nil {
1637 return nil
1638 }
1639 onuID := onuDevice.ProxyAddress.OnuId
1640 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1641 onuKey := dh.formOnuKey(intfID, onuID)
1642
1643 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1644 dh.onus.Store(onuKey, onuDev)
1645 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1646 return onuDev
1647}
1648
1649func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001650 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001651 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301652 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001653
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301654 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1655 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1656 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1657 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1658 if onuDev != nil {
1659 var onuGemInfo *rsrcMgr.OnuGemInfo
1660 var err error
1661 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1662 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1663 return false, err
1664 }
1665 if onuGemInfo != nil {
1666 for _, uni := range onuGemInfo.UniPorts {
1667 uniID := plt.UniIDFromPortNum(uni)
1668 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1669 if len(tpIDs) != 0 {
1670 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1671 tpInstExists = true
1672 break
1673 }
1674 }
1675 }
1676 }
1677 return tpInstExists, nil
1678 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301679
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301680 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1681 ParentId: dh.device.Id,
1682 SerialNumber: sn,
1683 ParentPortNo: parentPortNo,
1684 })
1685 if onuDevice != nil {
1686 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1687 return true, nil
1688 }
1689 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1690
1691 return false, nil
1692
1693}
1694
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001695// processDiscONULOSClear clears the LOS Alarm if it's needed
1696func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301697 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001698 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301699
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001700 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1701 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1702 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1703 OnuLosRaise event sent for it */
1704 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1705 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1706 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1707 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1708 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1709 "currentIntfId": onuDiscInd.GetIntfId()})
1710 // TODO:: Should we need to ignore raising OnuLosClear event
1711 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301712 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001713 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1714 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1715 alarmInd.LosStatus = statusCheckOff
1716 go func() {
1717 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1718 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1719 }
1720 }()
1721 // stop iterating
1722 return false
1723 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301724 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001725 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301726}
1727
1728func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1729 channelID := onuDiscInd.GetIntfId()
1730 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1731
1732 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1733 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1734
1735 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1736 if errtp != nil {
1737 return errtp
1738 }
1739 if tpInstExists {
1740 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001741 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001742 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001743 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001744 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1745
1746 // if the ONU existed, handle the LOS Alarm
1747 if existing {
1748
1749 if inProcess.(bool) {
1750 // if we're currently processing the ONU on a different thread, do nothing
1751 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1752 return nil
1753 }
1754 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1755 // then continue processing it
1756 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1757
1758 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001759 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301760 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001761
1762 defer func() {
1763 // once the function completes set the value to false so that
1764 // we know the processing has inProcess.
1765 // Note that this is done after checking if we are already processing
1766 // to avoid changing the value from a different thread
1767 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1768 dh.discOnus.Store(sn, false)
1769 }()
1770
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001771 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001772
1773 // check the ONU is already know to the OLT
1774 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001775 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001776 ParentId: dh.device.Id,
1777 SerialNumber: sn,
1778 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001779
1780 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001782 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Debugw(ctx, "core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001784 switch e.Code() {
1785 case codes.Internal:
1786 // this probably means NOT FOUND, so just create a new device
1787 onuDevice = nil
1788 case codes.DeadlineExceeded:
1789 // if the call times out, cleanup and exit
1790 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001791 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001792 }
1793 }
1794 }
1795
1796 if onuDevice == nil {
1797 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001798 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001799 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001800 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001801 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001802
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001804
1805 if err != nil {
1806 // if we can't create an ID in resource manager,
1807 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001808 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001809 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001810 "pon-intf-id": ponintfid,
1811 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001812 }
1813
khenaidoodc2116e2021-10-19 17:33:19 -04001814 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001815 ParentId: dh.device.Id,
1816 ParentPortNo: parentPortNo,
1817 ChannelId: channelID,
1818 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1819 SerialNumber: sn,
1820 OnuId: onuID,
1821 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001822 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001823 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301824 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001825 "pon-intf-id": ponintfid,
1826 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001827 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001828 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001829 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001830 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001831 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301832 log.Fields{"onuDevice": onuDevice,
1833 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001834 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301835 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001836 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001837
khenaidoo106c61a2021-08-11 18:05:46 -04001838 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1839 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1840 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1841 cancel()
1842 if err != nil {
1843 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1844 }
1845
Matteo Scandolo945e4012019-12-12 14:16:11 -08001846 // we can now use the existing ONU Id
1847 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001848 //Insert the ONU into cache to use in OnuIndication.
1849 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001851 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301852 "intfId": onuDiscInd.GetIntfId(),
1853 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001854 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001855
khenaidoo106c61a2021-08-11 18:05:46 -04001856 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301857 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301859 log.Fields{"onu": onuDev,
1860 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001861
khenaidoodc2116e2021-10-19 17:33:19 -04001862 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001863 DeviceId: onuDevice.Id,
1864 ParentDeviceId: dh.device.Id,
1865 OperStatus: common.OperStatus_DISCOVERED,
1866 ConnStatus: common.ConnectStatus_REACHABLE,
1867 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301868 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001869 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001870 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001871 }
khenaidoo106c61a2021-08-11 18:05:46 -04001872
Neha Sharma96b7bf22020-06-15 10:37:32 +00001873 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001874 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301875 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001876 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001877 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001878 }
1879 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001880}
1881
Mahir Gunyelb0046752021-02-26 13:51:05 -08001882func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001883
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001884 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001885 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001886 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001887 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001888 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301889 log.Fields{"onuId": onuInd.OnuId,
1890 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301891 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001892 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001893 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301894
David K. Bainbridge794735f2020-02-11 21:01:37 -08001895 errFields := log.Fields{"device-id": dh.device.Id}
1896
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301897 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1898
Mahir Gunyele77977b2019-06-27 05:36:22 -07001899 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1900 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001901 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001902 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001903 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001904 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1905 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001906 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001907 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001908 errFields["onu-id"] = onuInd.OnuId
1909 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001910 }
khenaidoodc2116e2021-10-19 17:33:19 -04001911 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001912 ParentId: dh.device.Id,
1913 SerialNumber: serialNumber,
1914 OnuId: onuInd.OnuId,
1915 ParentPortNo: ponPort,
1916 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001917 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001918
David K. Bainbridge794735f2020-02-11 21:01:37 -08001919 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001920 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001921 }
1922
David K. Bainbridge794735f2020-02-11 21:01:37 -08001923 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001924 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001925 "previousIntfId": onuDevice.ParentPortNo,
1926 "currentIntfId": ponPort})
1927 }
1928
1929 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001930 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301931 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1932 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301933 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001934 }
1935 if !foundInCache {
1936 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1937
khenaidoo106c61a2021-08-11 18:05:46 -04001938 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001939
1940 }
kesavand7cf3a052020-08-28 12:49:18 +05301941 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001942 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001943 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301944 }
1945 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001946 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001947 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001948 }
1949 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001950}
1951
Neha Sharma96b7bf22020-06-15 10:37:32 +00001952func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001953 logger.Debugw(ctx, "onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdra748de5c2020-07-01 10:27:52 -07001954 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1955 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1956 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1957 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001958 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001959 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1960 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001961 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001962 onuInd.OperState = "down"
1963 }
1964 }
1965
David K. Bainbridge794735f2020-02-11 21:01:37 -08001966 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001967 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001968 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
khenaidoo106c61a2021-08-11 18:05:46 -04001969
khenaidoodc2116e2021-10-19 17:33:19 -04001970 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001971 DeviceId: onuDevice.Id,
1972 OnuIndication: onuInd,
1973 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001974 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301975 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001976 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001977 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001978 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001979 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001980 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001981 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001982 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001983 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001984 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001985}
1986
cuilin20187b2a8c32019-03-26 19:52:28 -07001987func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1988 if serialNum != nil {
1989 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001990 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001991 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001992}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001993func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1994 decodedStr, err := hex.DecodeString(serialNum[4:])
1995 if err != nil {
1996 return nil, err
1997 }
1998 return &oop.SerialNumber{
1999 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002000 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002001 }, nil
2002}
cuilin20187b2a8c32019-03-26 19:52:28 -07002003
2004func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002005 if len(vendorSpecific) > 3 {
2006 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2007 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2008 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2009 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2010 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2011 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2012 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2013 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2014 return tmp
2015 }
2016 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002017}
2018
Mahir Gunyela2e68702022-12-07 00:00:42 -08002019// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002020func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302021 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002022}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002023
Mahir Gunyela2e68702022-12-07 00:00:42 -08002024// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002025func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2026 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302027 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002028 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302029 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002030
khenaidoodc2116e2021-10-19 17:33:19 -04002031 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002032 ParentId: dh.device.Id,
2033 OnuId: onuID,
2034 ParentPortNo: parentPort,
2035 })
2036
Girish Gowdru0c588b22019-04-23 23:24:56 -04002037 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002038 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002039 "intf-id": parentPort,
2040 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002041 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 logger.Debugw(ctx, "successfully-received-child-device-from-core", log.Fields{"child-device-id": onuDevice.Id, "child-device-sn": onuDevice.SerialNumber})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002043 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302044}
2045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002046// SendPacketInToCore sends packet-in to core
2047// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2048// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002049func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002050 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002052 "port": logicalPort,
2053 "packet": hex.EncodeToString(packetPayload),
2054 "device-id": dh.device.Id,
2055 })
2056 }
khenaidoo106c61a2021-08-11 18:05:46 -04002057
khenaidoodc2116e2021-10-19 17:33:19 -04002058 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002059 DeviceId: dh.device.Id,
2060 Port: logicalPort,
2061 Packet: packetPayload,
2062 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302063 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002064 "source": "adapter",
2065 "destination": "core",
2066 "device-id": dh.device.Id,
2067 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002068 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002069 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002070 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002071 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002072 "packet": hex.EncodeToString(packetPayload),
2073 "device-id": dh.device.Id,
2074 })
2075 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002076 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002077}
2078
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002079// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002080func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002081 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002082
2083 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2084 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002085 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002086 }
2087
Kent Hagermane6ff1012020-07-14 15:07:53 -04002088 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002089 metrics := dh.metrics.GetSubscriberMetrics()
2090 for _, m := range pmConfigs.Metrics {
2091 metrics[m.Name].Enabled = m.Enabled
2092
2093 }
2094 }
2095}
2096
khenaidoodc2116e2021-10-19 17:33:19 -04002097func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002098 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002099 var errorsList []error
2100
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002101 if dh.getDeviceDeletionInProgressFlag() {
2102 // The device itself is going to be reset as part of deletion. So nothing to be done.
2103 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2104 return nil
2105 }
2106
Girish Gowdru0c588b22019-04-23 23:24:56 -04002107 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002108 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00002109 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002110
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302112 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002113 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302114 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002115 if flow_utils.HasGroup(flow) {
2116 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2117 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002118 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2119 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2120 } else {
2121 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2122 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002123 }
Girish Gowdracefae192020-03-19 18:14:10 -07002124 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002125 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
2126 //The flow we want to remove is not there, there is no need to throw an error
2127 logger.Warnw(ctx, "flow-to-remove-not-found",
2128 log.Fields{
2129 "ponIf": intfID,
2130 "flowToRemove": flow,
2131 "error": err,
2132 })
2133 } else {
2134 errorsList = append(errorsList, err)
2135 }
Girish Gowdracefae192020-03-19 18:14:10 -07002136 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002137 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302138
2139 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00002140 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302142 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002143 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302144 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002145 if flow_utils.HasGroup(flow) {
2146 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2147 } else {
yasin saplid0566272021-12-21 09:10:30 +00002148 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002149 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2150 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2151 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2152 } else {
yasin saplid0566272021-12-21 09:10:30 +00002153 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002154 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002155 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002156 if err != nil {
2157 errorsList = append(errorsList, err)
2158 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302159 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002160 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002161
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002162 return errorsList
2163}
2164
2165func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2166 var err error
2167 var errorsList []error
2168
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002169 if dh.getDeviceDeletionInProgressFlag() {
2170 // The device itself is going to be reset as part of deletion. So nothing to be done.
2171 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2172 return nil
2173 }
2174
Girish Gowdracefae192020-03-19 18:14:10 -07002175 // Whether we need to synchronize multicast group adds and modifies like flow add and delete needs to be investigated
Esin Karamanccb714b2019-11-29 15:02:06 +00002176 if groups != nil {
2177 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002178 // err = dh.groupMgr.AddGroup(ctx, group)
2179 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002180 if err != nil {
2181 errorsList = append(errorsList, err)
2182 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002183 }
2184 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002185 // err = dh.groupMgr.ModifyGroup(ctx, group)
2186 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002187 if err != nil {
2188 errorsList = append(errorsList, err)
2189 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002190 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002191 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002192 // err = dh.groupMgr.DeleteGroup(ctx, group)
2193 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002194 if err != nil {
2195 errorsList = append(errorsList, err)
2196 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002197 }
2198 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002199
2200 return errorsList
2201}
2202
Mahir Gunyela2e68702022-12-07 00:00:42 -08002203// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002204func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *of.FlowMetadata) error {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002205
2206 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002207
2208 if dh.getDeviceDeletionInProgressFlag() {
2209 // The device itself is going to be reset as part of deletion. So nothing to be done.
2210 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2211 return nil
2212 }
2213
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002214 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2215 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2216 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002217 if len(errorsList) > 0 {
2218 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2219 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002220 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002221 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302222}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002223
Mahir Gunyela2e68702022-12-07 00:00:42 -08002224// DisableDevice disables the given device
2225// It marks the following for the given device:
2226// Device-Handler Admin-State : down
2227// Device Port-State: UNKNOWN
2228// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002229func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002230 /* On device disable ,admin state update has to be done prior sending request to agent since
2231 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002232 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002233 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002234 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002235 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002236 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002237 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002238 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002239 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002240 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002241 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302242
2243 dh.discOnus = sync.Map{}
2244 dh.onus = sync.Map{}
2245
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002246 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302247 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002248 if dh.isCollectorActive {
2249 dh.stopCollector <- true
2250 }
2251 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302252
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002254 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302255 //Update device Admin state
2256 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002257
kdarapu1afeceb2020-02-12 01:38:09 -05002258 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
khenaidoodc2116e2021-10-19 17:33:19 -04002259 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002260 DeviceId: cloned.Id,
2261 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2262 OperStatus: voltha.OperStatus_UNKNOWN,
2263 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002264 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002265 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002266 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002267 return nil
2268}
2269
Neha Sharma96b7bf22020-06-15 10:37:32 +00002270func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002271 // Update onu state as unreachable in onu adapter
2272 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302273 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002274
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002275 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002276 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002277 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002278 logger.Errorw(ctx, "failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002279 }
2280 if onuDevices != nil {
2281 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002282 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002283 DeviceId: onuDevice.Id,
2284 OnuIndication: &onuInd,
2285 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002286 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002287 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002288 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002289 }
2290
2291 }
2292 }
2293
2294}
2295
Mahir Gunyela2e68702022-12-07 00:00:42 -08002296// ReenableDevice re-enables the olt device after disable
2297// It marks the following for the given device:
2298// Device-Handler Admin-State : up
2299// Device Port-State: ACTIVE
2300// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302302 if dh.Client != nil {
2303 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2304 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2305 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2306 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302307 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302308 } else {
2309 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2310
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302311 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302312
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002314
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002315 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002316 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002317 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002318 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002319 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2320 } else {
2321 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2322 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2323 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002324 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002325 if retError == nil {
2326 //Update the device oper status as ACTIVE
2327 device.OperStatus = voltha.OperStatus_ACTIVE
2328 } else {
2329 //Update the device oper status as FAILED
2330 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002331 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002332 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002333
khenaidoodc2116e2021-10-19 17:33:19 -04002334 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002335 DeviceId: device.Id,
2336 OperStatus: device.OperStatus,
2337 ConnStatus: device.ConnectStatus,
2338 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302339 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002340 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002341 "connect-status": device.ConnectStatus,
2342 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002343 }
kesavand39e0aa32020-01-28 20:58:50 -05002344
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002346
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002347 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002348}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002349
npujarec5762e2020-01-01 14:08:48 +05302350func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002351 var uniID uint32
2352 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002353 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302354 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002355 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002356 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002357 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002358 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2359 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2360 } else {
2361 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2362 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002363 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002364 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002365 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002366 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002367 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002368 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002369 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002371 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002372 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002373 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002374 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002375 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002376 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002377 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302379 }
yasin saplibddc2d72022-02-08 13:10:17 +00002380 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2381 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002382 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002383 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302384 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002385 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002386 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387 logger.Debugw(ctx, "failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002388 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002389 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002390 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002391 if len(errs) > 0 {
2392 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2393 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2394 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002395 return nil
2396}
2397
Devmalya Paul495b94a2019-08-27 19:42:00 -04002398// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
npujarec5762e2020-01-01 14:08:48 +05302399func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002400 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002401 /* Clear the KV store data associated with the all the UNI ports
2402 This clears up flow data and also resource map data for various
2403 other pon resources like alloc_id and gemport_id
2404 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002405
2406 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002407
2408 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002409
Gustavo Silva41af9122022-10-11 11:05:13 -03002410 err := dh.cleanupDeviceResources(ctx)
2411 if err != nil {
2412 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2413 } else {
2414 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2415 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002416
Himani Chawla49a5d562020-11-25 11:53:44 +05302417 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002418 // Stop the Stats collector
2419 if dh.isCollectorActive {
2420 dh.stopCollector <- true
2421 }
2422 // stop the heartbeat check routine
2423 if dh.isHeartbeatCheckActive {
2424 dh.stopHeartbeatCheck <- true
2425 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302426 // Stop the read indication only if it the routine is active
2427 if dh.isReadIndicationRoutineActive {
2428 dh.stopIndications <- true
2429 }
2430 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002431 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002432 //Reset the state
2433 if dh.Client != nil {
2434 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002435 go func() {
2436 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2437 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2438 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2439 }
2440 }()
2441 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002442 }
2443 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002444 // There is no need to update the core about operation status and connection status of the OLT.
2445 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2446 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2447 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002448
khenaidoo7eb2d672021-10-22 19:08:50 -04002449 // Stop the adapter grpc clients for that parent device
2450 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002451 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002452}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002453
2454// StopAllFlowRoutines stops all flow routines
2455func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2456 var wg sync.WaitGroup
2457 wg.Add(1) // for the mcast routine below to finish
2458 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2459 for _, flMgr := range dh.flowMgr {
2460 if flMgr != nil {
2461 wg.Add(1) // for the flow handler routine below to finish
2462 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2463 }
2464 }
2465 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2466 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2467 } else {
2468 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2469 }
2470}
2471
Gustavo Silva41af9122022-10-11 11:05:13 -03002472func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2473 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002474 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302475 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002476 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002477 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002478 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002479 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002480 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2481 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302482 }
2483 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002484 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2485 errs = append(errs, err)
2486 }
2487 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2488 errs = append(errs, err)
2489 }
2490 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2491 errs = append(errs, err)
2492 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002493 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002494 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002495 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002496 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002497 }
2498 // Clean up NNI manager's data
2499 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2500 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002501 }
A R Karthick1f85b802019-10-11 05:06:05 +00002502
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002503 dh.CloseKVClient(ctx)
2504
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002505 // Take one final sweep at cleaning up KV store for the OLT device
2506 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002507 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2508 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002509 }
2510
Devmalya Paul495b94a2019-08-27 19:42:00 -04002511 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302512 dh.onus.Range(func(key interface{}, value interface{}) bool {
2513 dh.onus.Delete(key)
2514 return true
2515 })
2516
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002517 /*Delete discovered ONU map for the device*/
2518 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2519 dh.discOnus.Delete(key)
2520 return true
2521 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002522 if len(errs) > 0 {
2523 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2524 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2525 }
2526 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002527}
2528
Mahir Gunyela2e68702022-12-07 00:00:42 -08002529// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002530func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302531 if dh.Client != nil {
2532 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2533 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2534 }
2535 } else {
2536 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2537
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002538 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302539
Neha Sharma96b7bf22020-06-15 10:37:32 +00002540 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002541 return nil
2542}
2543
David K. Bainbridge794735f2020-02-11 21:01:37 -08002544func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002545 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002546 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002547 "packet-indication": *packetIn,
2548 "device-id": dh.device.Id,
2549 "packet": hex.EncodeToString(packetIn.Pkt),
2550 })
2551 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002552 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2553 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2554 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002555 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002556 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002557 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002558 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002559 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002560 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002561 "logical-port-num": logicalPortNum,
2562 "device-id": dh.device.Id,
2563 "packet": hex.EncodeToString(packetIn.Pkt),
2564 })
2565 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002566
khenaidoodc2116e2021-10-19 17:33:19 -04002567 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002568 DeviceId: dh.device.Id,
2569 Port: logicalPortNum,
2570 Packet: packetIn.Pkt,
2571 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302572 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002573 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302574 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002575 "device-id": dh.device.Id,
2576 "packet": hex.EncodeToString(packetIn.Pkt),
2577 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002578 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002579
Matteo Scandolo92186242020-06-12 10:54:18 -07002580 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002581 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002582 "packet": hex.EncodeToString(packetIn.Pkt),
2583 "device-id": dh.device.Id,
2584 })
2585 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002586 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002587}
2588
Mahir Gunyela2e68702022-12-07 00:00:42 -08002589// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2590func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2591 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2592 if err != nil {
2593 return olterrors.NewErrInvalidValue(log.Fields{
2594 "egress-nni-port": egressPortNo,
2595 "device-id": dh.device.Id,
2596 }, err)
2597 }
2598 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2599
2600 if logger.V(log.DebugLevel) {
2601 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2602 "uplink-pkt": uplinkPkt,
2603 "packet": hex.EncodeToString(packet.Data),
2604 "device-id": dh.device.Id,
2605 })
2606 }
2607
2608 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2609 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2610 "packet": hex.EncodeToString(packet.Data),
2611 "device-id": dh.device.Id,
2612 }, err)
2613 }
2614 return nil
2615}
2616
2617// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2618func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2619 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2620 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2621 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2622 // Do not packet-out lldp packets on uni port.
2623 // ONOS has no clue about uni/nni ports, it just packets out on all
2624 // available ports on the Logical Switch. It should not be interested
2625 // in the UNI links.
2626 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2627 "device-id": dh.device.Id,
2628 })
2629 return nil
2630 }
2631 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2632 if innerEthType == 0x8100 {
2633 // q-in-q 802.1ad or 802.1q double tagged packet.
2634 // slice out the outer tag.
2635 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2636 if logger.V(log.DebugLevel) {
2637 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2638 "packet-data": hex.EncodeToString(packet.Data),
2639 "device-id": dh.device.Id,
2640 })
2641 }
2642 }
2643 }
2644 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2645 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2646 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2647 var gemPortID uint32
2648 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2649 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2650 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2651 }
2652 if err != nil {
2653 // In this case the openolt agent will receive the gemPortID as 0.
2654 // The agent tries to retrieve the gemPortID in this case.
2655 // This may not always succeed at the agent and packetOut may fail.
2656 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2657 "intf-id": intfID,
2658 "onu-id": onuID,
2659 "uni-id": uniID,
2660 "packet": hex.EncodeToString(packet.Data),
2661 "device-id": dh.device.Id,
2662 "error": err,
2663 })
2664 }
2665
2666 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2667 if logger.V(log.DebugLevel) {
2668 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2669 "egress-port-no": egressPortNo,
2670 "intf-id": intfID,
2671 "onu-id": onuID,
2672 "uni-id": uniID,
2673 "gem-port-id": gemPortID,
2674 "packet": hex.EncodeToString(packet.Data),
2675 "device-id": dh.device.Id,
2676 })
2677 }
2678
2679 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2680 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2681 "source": "adapter",
2682 "destination": "onu",
2683 "egress-port-number": egressPortNo,
2684 "intf-id": intfID,
2685 "oni-id": onuID,
2686 "uni-id": uniID,
2687 "gem-port-id": gemPortID,
2688 "packet": hex.EncodeToString(packet.Data),
2689 "device-id": dh.device.Id,
2690 }, err)
2691 }
2692 return nil
2693}
2694
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002695// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002696func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002697 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002698 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002699 "device-id": dh.device.Id,
2700 "egress-port-no": egressPortNo,
2701 "pkt-length": len(packet.Data),
2702 "packet": hex.EncodeToString(packet.Data),
2703 })
2704 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002705
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002706 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002707 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002708 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002709 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002711 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002712 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002713 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302714 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002715 "egressPortType": egressPortType,
2716 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302717 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002718 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002719 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002720 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002721}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002722
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002723func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2724 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002725}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302726
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002727func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002728
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002729 defer func() {
2730 dh.lockDevice.Lock()
2731 dh.isHeartbeatCheckActive = false
2732 dh.lockDevice.Unlock()
2733 }()
2734
2735 dh.lockDevice.Lock()
2736 dh.isHeartbeatCheckActive = true
2737 dh.lockDevice.Unlock()
2738
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302739 // start the heartbeat check towards the OLT.
2740 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302741 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302742
2743 for {
2744 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2745 select {
2746 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002747 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002748 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002749 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302750 if timerCheck == nil {
2751 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002752 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302753 }
2754 } else {
2755 if timerCheck != nil {
2756 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002757 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302758 }
2759 timerCheck = nil
2760 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302761 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2762 if dh.heartbeatSignature == 0 {
2763 // First time the signature will be 0, update the signture to DB when not found.
2764 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2765 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2766 }
2767 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2768
2769 dh.lockDevice.RLock()
2770 // Stop the read indication only if it the routine is active
2771 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2772 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2773 // on next execution of the readIndication routine.
2774 if !dh.isReadIndicationRoutineActive {
2775 // Start reading indications
2776 go func() {
2777 if err = dh.readIndications(ctx); err != nil {
2778 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2779 }
2780 }()
2781 }
2782 dh.lockDevice.RUnlock()
2783
2784 } else {
2785 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2786 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2787 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2788 go dh.updateStateRebooted(ctx)
2789 }
2790
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302791 }
2792 cancel()
2793 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002794 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302795 return
2796 }
2797 }
2798}
2799
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002800func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002801 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002802 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002803 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2804 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2805 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2806 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2807 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002808 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002809 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2810 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002811 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302812
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302813 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002814 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002815 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002816 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002817 DeviceId: dh.device.Id,
2818 OperStatus: voltha.OperStatus_UNKNOWN,
2819 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2820 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002821 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002822 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302823 /*
2824 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2825 DeviceId: dh.device.Id,
2826 PortTypeFilter: 0,
2827 OperStatus: voltha.OperStatus_UNKNOWN,
2828 }); err != nil {
2829 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2830 }
2831 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002832
2833 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002834 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002835 cloned := proto.Clone(device).(*voltha.Device)
2836 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2837 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2838 dh.device = cloned // update local copy of the device
2839 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002840
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002841 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002842 // Stop the Stats collector
2843 if dh.isCollectorActive {
2844 dh.stopCollector <- true
2845 }
2846 // stop the heartbeat check routine
2847 if dh.isHeartbeatCheckActive {
2848 dh.stopHeartbeatCheck <- true
2849 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002850 // Stop the read indication only if it the routine is active
2851 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2852 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2853 // on next execution of the readIndication routine.
2854 if dh.isReadIndicationRoutineActive {
2855 dh.stopIndications <- true
2856 }
2857 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002858 dh.transitionMap.Handle(ctx, DeviceInit)
2859
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302860 }
2861}
kesavand39e0aa32020-01-28 20:58:50 -05002862
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302863func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2864 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2865 if err != nil || device == nil {
2866 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2867 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2868 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2869 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2870 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2871 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2872 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2873 return
2874 }
2875
2876 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2877 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2878 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2879 DeviceId: dh.device.Id,
2880 OperStatus: voltha.OperStatus_REBOOTED,
2881 ConnStatus: voltha.ConnectStatus_REACHABLE,
2882 }); err != nil {
2883 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2884 }
2885
2886 dh.lockDevice.RLock()
2887 // Stop the read indication only if it the routine is active
2888 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2889 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2890 // on next execution of the readIndication routine.
2891 if dh.isReadIndicationRoutineActive {
2892 dh.stopIndications <- true
2893 }
2894 dh.lockDevice.RUnlock()
2895
2896 //raise olt communication failure event
2897 raisedTs := time.Now().Unix()
2898 cloned := proto.Clone(device).(*voltha.Device)
2899 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2900 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2901 dh.device = cloned // update local copy of the device
2902 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2903
Gustavo Silva41af9122022-10-11 11:05:13 -03002904 if err := dh.cleanupDeviceResources(ctx); err != nil {
2905 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2906 } else {
2907 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2908 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002909
2910 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302911 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002912 if dh.isCollectorActive {
2913 dh.stopCollector <- true
2914 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302915 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002916 if dh.isHeartbeatCheckActive {
2917 dh.stopHeartbeatCheck <- true
2918 }
2919 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302920
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002921 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302922
2923 //reset adapter reconcile flag
2924 dh.adapterPreviouslyConnected = false
2925 for {
2926
2927 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2928 if err != nil || childDevices == nil {
2929 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2930 continue
2931 }
2932 if len(childDevices.Items) == 0 {
2933 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2934 break
2935 } else {
2936 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2937 time.Sleep(5 * time.Second)
2938 }
2939
2940 }
2941 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2942 dh.transitionMap.Handle(ctx, DeviceInit)
2943
2944}
2945
kesavand39e0aa32020-01-28 20:58:50 -05002946// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002947func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2948 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2949 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002950}
2951
2952// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002953func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2954 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2955 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002956}
2957
Mahir Gunyela2e68702022-12-07 00:00:42 -08002958// modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002959func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2960 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002961 if port.GetType() == voltha.Port_ETHERNET_NNI {
2962 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302964 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302965 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002966 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002967 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002968 }
2969 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002970 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002971 ponIntf := &oop.Interface{IntfId: ponID}
2972 var operStatus voltha.OperStatus_Types
2973 if enablePort {
2974 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302975 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002976
2977 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302978 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002979 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002980 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002981 }
2982 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002983 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002984 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002985 } else {
2986 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302987 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002988 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302989 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002990 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002991 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002992 }
2993 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002994 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002995 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002996 }
khenaidoodc2116e2021-10-19 17:33:19 -04002997 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002998 DeviceId: dh.device.Id,
2999 PortType: voltha.Port_PON_OLT,
3000 PortNo: port.PortNo,
3001 OperStatus: operStatus,
3002 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303003 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303004 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003005 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003006 }
3007 return nil
3008}
3009
Mahir Gunyela2e68702022-12-07 00:00:42 -08003010// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003011func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003012 // Disable the port and update the oper_port_status to core
3013 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003014 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003015 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303017 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303018 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003019 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003020 }
3021 }
3022 }
3023 return nil
3024}
3025
Mahir Gunyela2e68702022-12-07 00:00:42 -08003026// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003027func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3028 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3029 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003030 if port.Type == voltha.Port_ETHERNET_NNI {
3031 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003032 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003033 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003034 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003035 }
3036 }
3037 if port.Type == voltha.Port_PON_OLT {
3038 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003039 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003040 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003041 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003042 }
3043 }
3044 }
3045}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003046
3047// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003048func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003049 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003050 if dh.getDeviceDeletionInProgressFlag() {
3051 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3052 // will reboot, so everything will be reset on the pOLT too.
3053 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3054 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3055 return nil
3056 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003057 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003058 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003059
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003060 var sn *oop.SerialNumber
3061 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003062 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303063 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003064 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303065 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003066 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003067 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003068
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003069 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003070 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003071 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003072 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3073 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3074 "device-id": dh.device.Id,
3075 "intf-id": intfID,
3076 "onuID": onuID,
3077 "err": err})
3078 } else {
3079 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003080 // Delete flows from device before schedulers and queue
3081 // Clear flowids for gem cache.
3082 removedFlows := []uint64{}
3083 for _, gem := range onuGem.GemPorts {
3084 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3085 for _, flowID := range flowIDs {
3086 //multiple gem port can have the same flow id
3087 //it is better to send only one flowRemove request to the agent
3088 var alreadyRemoved bool
3089 for _, removedFlowID := range removedFlows {
3090 if removedFlowID == flowID {
3091 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3092 alreadyRemoved = true
3093 break
3094 }
3095 }
3096 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003097 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003098 removedFlows = appendUnique64bit(removedFlows, flowID)
3099 }
3100 }
3101 }
3102 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3103 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003104 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3105 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3106 "device-id": dh.device.Id,
3107 "onu-device": onu,
3108 "err": err})
3109 }
yasin saplibddc2d72022-02-08 13:10:17 +00003110 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003111 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3112 "intf-id": intfID,
3113 "onu-device": onu,
3114 "onu-gem": onuGem,
3115 "err": err})
3116 //Not returning error on cleanup.
3117 }
3118 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05303119
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003120 }
yasin saplibddc2d72022-02-08 13:10:17 +00003121 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003122 dh.onus.Delete(onuKey)
3123 dh.discOnus.Delete(onuSn)
3124
3125 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003126 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303127 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303128 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003129 "onu-id": onuID}, err).Log()
3130 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003131
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003132 return nil
3133}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003134func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3135 flow := &oop.Flow{FlowId: flowID}
3136 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3137 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3138 "device-id": dh.device.Id})
3139 } else {
3140 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3141 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3142 "device-id": dh.device.Id,
3143 "err": err})
3144 }
3145 }
3146}
Girish Gowdracefae192020-03-19 18:14:10 -07003147
3148func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003149 for _, field := range flow_utils.GetOfbFields(flow) {
3150 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003151 return field.GetPort()
3152 }
3153 }
3154 return InvalidPort
3155}
3156
3157func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003158 for _, action := range flow_utils.GetActions(flow) {
3159 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003160 if out := action.GetOutput(); out != nil {
3161 return out.GetPort()
3162 }
3163 }
3164 }
3165 return InvalidPort
3166}
3167
Girish Gowdracefae192020-03-19 18:14:10 -07003168func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3169 inPort := getInPortFromFlow(flow)
3170 outPort := getOutPortFromFlow(flow)
3171
3172 if inPort == InvalidPort || outPort == InvalidPort {
3173 return inPort, outPort
3174 }
3175
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003176 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003177 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003178 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003179 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003180 return uniPort, outPort
3181 }
3182 }
3183 } else {
3184 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003185 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003186 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003187 return inPort, uniPort
3188 }
3189 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003190 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003191 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003192 return uniPort, outPort
3193 }
3194 }
3195 }
3196
3197 return InvalidPort, InvalidPort
3198}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003199
3200func extractOmciTransactionID(omciPkt []byte) uint16 {
3201 if len(omciPkt) > 3 {
3202 d := omciPkt[0:2]
3203 transid := binary.BigEndian.Uint16(d)
3204 return transid
3205 }
3206 return 0
3207}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003208
3209// StoreOnuDevice stores the onu parameters to the local cache.
3210func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3211 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3212 dh.onus.Store(onuKey, onuDevice)
3213}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003214
khenaidoodc2116e2021-10-19 17:33:19 -04003215func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003216 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003217 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003218 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003219 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003220 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003221 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003222 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003223 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3224 return nil, err
3225 }
3226 ID = device.ProxyAddress.GetOnuId()
3227 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3228 valueparam.Onu = &Onu
3229 valueparam.Value = value
3230
3231 // This API is unsupported until agent patch is added
3232 resp.Unsupported = uint32(value)
3233 _ = ctx
3234
3235 // Uncomment this code once agent changes are complete and tests
3236 /*
3237 resp, err = dh.Client.GetValue(ctx, valueparam)
3238 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003239 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003240 return nil, err
3241 }
3242 */
3243
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003244 logger.Infow(ctx, "get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003245 return resp, nil
3246}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003247
yasin saplid0566272021-12-21 09:10:30 +00003248func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3249 // Default to NNI
3250 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003251 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003252 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003253 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003254 }
3255 return intfID
3256}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003257
Mahir Gunyelb0046752021-02-26 13:51:05 -08003258func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3259 dh.perPonOnuIndicationChannelLock.Lock()
3260 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3261 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003262 return ch.indicationChannel
3263 }
3264 channels := onuIndicationChannels{
3265 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003266 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003267 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003268 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003269 stopChannel: make(chan struct{}),
3270 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003271 dh.perPonOnuIndicationChannel[intfID] = channels
3272 dh.perPonOnuIndicationChannelLock.Unlock()
3273 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003274 return channels.indicationChannel
3275
3276}
3277
Mahir Gunyelb0046752021-02-26 13:51:05 -08003278func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3279 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3280 dh.perPonOnuIndicationChannelLock.Lock()
3281 defer dh.perPonOnuIndicationChannelLock.Unlock()
3282 for _, v := range dh.perPonOnuIndicationChannel {
3283 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003284 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003285 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003286}
3287
Mahir Gunyelb0046752021-02-26 13:51:05 -08003288func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3289 ind := onuIndicationMsg{
3290 ctx: ctx,
3291 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003292 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003293 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003294 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003295 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003296}
3297
Mahir Gunyelb0046752021-02-26 13:51:05 -08003298func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003299 for {
3300 select {
3301 // process one indication per onu, before proceeding to the next one
3302 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003303 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003304 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003305 "ind": indication})
3306 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003307 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003308 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003309 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3310 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003311 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003312 }
3313 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003314 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003315 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3316 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003317 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003318 }
3319 }
3320 case <-onuChannels.stopChannel:
3321 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3322 close(onuChannels.indicationChannel)
3323 return
3324 }
3325 }
3326}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003327
3328// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3329// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003330func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003331 if dh.getDeviceDeletionInProgressFlag() {
3332 // The device itself is going to be reset as part of deletion. So nothing to be done.
3333 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3334 return nil
3335 }
3336
Girish Gowdra491a9c62021-01-06 16:43:07 -08003337 // Step1 : Fill McastFlowOrGroupControlBlock
3338 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3339 // Step3 : Wait on response channel for response
3340 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003341 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003342 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3343 errChan := make(chan error)
3344 var groupID uint32
3345 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3346 ctx: ctx,
3347 flowOrGroupAction: action,
3348 flow: flow,
3349 group: group,
3350 errChan: &errChan,
3351 }
3352 if flow != nil {
3353 groupID = flow_utils.GetGroup(flow)
3354 } else if group != nil {
3355 groupID = group.Desc.GroupId
3356 } else {
3357 return errors.New("flow-and-group-both-nil")
3358 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003359 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3360 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3361 // Derive the appropriate go routine to handle the request by a simple module operation.
3362 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3363 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3364 // Wait for handler to return error value
3365 err := <-errChan
3366 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3367 return err
3368 }
3369 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3370 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003371}
3372
3373// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003374func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003375 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003376 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003377 // block on the channel to receive an incoming mcast flow/group
3378 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003379 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3380 if mcastFlowOrGroupCb.flow != nil {
3381 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3382 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3383 log.Fields{"device-id": dh.device.Id,
3384 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003385 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3386 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3387 for _, flMgr := range dh.flowMgr {
3388 if flMgr != nil {
3389 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3390 break
3391 }
3392 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003393 // Pass the return value over the return channel
3394 *mcastFlowOrGroupCb.errChan <- err
3395 } else { // flow remove
3396 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3397 log.Fields{"device-id": dh.device.Id,
3398 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003399 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3400 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3401 for _, flMgr := range dh.flowMgr {
3402 if flMgr != nil {
3403 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3404 break
3405 }
3406 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003407 // Pass the return value over the return channel
3408 *mcastFlowOrGroupCb.errChan <- err
3409 }
3410 } else { // mcast group
3411 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3412 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3413 log.Fields{"device-id": dh.device.Id,
3414 "groupToAdd": mcastFlowOrGroupCb.group})
3415 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3416 // Pass the return value over the return channel
3417 *mcastFlowOrGroupCb.errChan <- err
3418 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3419 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3420 log.Fields{"device-id": dh.device.Id,
3421 "groupToModify": mcastFlowOrGroupCb.group})
3422 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3423 // Pass the return value over the return channel
3424 *mcastFlowOrGroupCb.errChan <- err
3425 } else { // group remove
3426 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3427 log.Fields{"device-id": dh.device.Id,
3428 "groupToRemove": mcastFlowOrGroupCb.group})
3429 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3430 // Pass the return value over the return channel
3431 *mcastFlowOrGroupCb.errChan <- err
3432 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003433 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003434 case <-stopHandler:
3435 dh.mcastHandlerRoutineActive[routineIndex] = false
3436 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003437 }
3438 }
3439}
kesavand62126212021-01-12 04:56:06 -05003440
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003441// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003442func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003443 for i, v := range dh.stopMcastHandlerRoutine {
3444 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003445 select {
3446 case v <- true:
3447 case <-time.After(time.Second * 5):
3448 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3449 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003450 }
3451 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003452
3453 if dh.incomingMcastFlowOrGroup != nil {
3454 for k := range dh.incomingMcastFlowOrGroup {
3455 if dh.incomingMcastFlowOrGroup[k] != nil {
3456 dh.incomingMcastFlowOrGroup[k] = nil
3457 }
3458 }
3459 dh.incomingMcastFlowOrGroup = nil
3460 }
3461
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003462 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003463 logger.Debug(ctx, "stopped all mcast handler routines")
3464}
3465
kesavand62126212021-01-12 04:56:06 -05003466func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3467
3468 singleValResp := extension.SingleGetValueResponse{
3469 Response: &extension.GetValueResponse{
3470 Response: &extension.GetValueResponse_PortCoutners{
3471 PortCoutners: &extension.GetOltPortCountersResponse{},
3472 },
3473 },
3474 }
3475
3476 errResp := func(status extension.GetValueResponse_Status,
3477 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3478 return &extension.SingleGetValueResponse{
3479 Response: &extension.GetValueResponse{
3480 Status: status,
3481 ErrReason: reason,
3482 },
3483 }
3484 }
3485
3486 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3487 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3488 //send error response
3489 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3490 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3491 }
3492 statIndChn := make(chan bool, 1)
3493 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3494 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3495 //request openOlt agent to send the the port statistics indication
3496
3497 go func() {
3498 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3499 if err != nil {
3500 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3501 }
3502 }()
3503 select {
3504 case <-statIndChn:
3505 //indication received for ports stats
3506 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3507 case <-time.After(oltPortInfoTimeout * time.Second):
3508 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3509 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3510 case <-ctx.Done():
3511 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3512 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3513 }
3514 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3515 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003516 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003517 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3518 cmnni := dh.portStats.collectNNIMetrics(intfID)
3519 if cmnni == nil {
3520 //TODO define the error reason
3521 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3522 }
3523 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3524 return &singleValResp
3525
3526 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3527 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003528 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003529 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3530 cmpon := dh.portStats.collectPONMetrics(intfID)
3531 if cmpon == nil {
3532 //TODO define the error reason
3533 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3534 }
3535 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3536 return &singleValResp
3537 }
3538 }
3539 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3540}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303541
3542func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3543
3544 singleValResp := extension.SingleGetValueResponse{
3545 Response: &extension.GetValueResponse{
3546 Response: &extension.GetValueResponse_OnuPonCounters{
3547 OnuPonCounters: &extension.GetOnuCountersResponse{},
3548 },
3549 },
3550 }
3551
3552 errResp := func(status extension.GetValueResponse_Status,
3553 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3554 return &extension.SingleGetValueResponse{
3555 Response: &extension.GetValueResponse{
3556 Status: status,
3557 ErrReason: reason,
3558 },
3559 }
3560 }
3561 intfID := onuPonInfo.IntfId
3562 onuID := onuPonInfo.OnuId
3563 onuKey := dh.formOnuKey(intfID, onuID)
3564
3565 if _, ok := dh.onus.Load(onuKey); !ok {
3566 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3567 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3568 }
3569 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3570 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3571 if cmnni == nil {
3572 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3573 }
3574 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3575 return &singleValResp
3576
3577}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003578
nikesh.krishnanc8473432023-06-14 12:14:54 +05303579func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
3580
3581 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3582 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3583 if err != nil {
3584 return nil, err
3585 }
3586 return OnuInfo, nil
3587
3588}
3589
3590func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
3591
3592 Intf := oop.Interface{IntfId: intfID}
3593 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3594 if err != nil {
3595 return nil, err
3596 }
3597 return IntfInfo, nil
3598
3599}
3600
Gamze Abaka85e9a142021-05-26 13:41:39 +00003601func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3602
3603 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3604 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3605 if err != nil {
3606 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3607 return generateSingleGetValueErrorResponse(err)
3608 }
3609 return &extension.SingleGetValueResponse{
3610 Response: &extension.GetValueResponse{
3611 Status: extension.GetValueResponse_OK,
3612 Response: &extension.GetValueResponse_RxPower{
3613 RxPower: &extension.GetRxPowerResponse{
3614 IntfId: rxPowerRequest.IntfId,
3615 OnuId: rxPowerRequest.OnuId,
3616 Status: rxPower.Status,
3617 FailReason: rxPower.FailReason.String(),
3618 RxPower: rxPower.RxPowerMeanDbm,
3619 },
3620 },
3621 },
3622 }
3623}
3624
praneeth nalmas55616d62023-02-06 09:19:18 +05303625func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
3626
3627 errResp := func(status extension.GetValueResponse_Status,
3628 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3629 return &extension.SingleGetValueResponse{
3630 Response: &extension.GetValueResponse{
3631 Status: status,
3632 ErrReason: reason,
3633 },
3634 }
3635 }
3636
3637 resp := extension.SingleGetValueResponse{
3638 Response: &extension.GetValueResponse{
3639 Status: extension.GetValueResponse_OK,
3640 Response: &extension.GetValueResponse_OltRxPower{
3641 OltRxPower: &extension.GetOltRxPowerResponse{},
3642 },
3643 },
3644 }
3645
3646 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3647 portLabel := OltRxPowerRequest.PortLabel
3648 serialNumber := OltRxPowerRequest.OnuSn
3649
3650 portInfo := strings.Split(portLabel, "-")
3651 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3652
3653 if err != nil {
3654 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3655 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3656 }
3657
3658 if portInfo[0] != "pon" {
3659 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3660 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3661 }
3662 ponIntdID := plt.PortNoToIntfID((uint32)(portNumber), voltha.Port_PON_OLT)
3663
3664 if serialNumber != "" {
3665
3666 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3667 if onuDev != nil {
3668
3669 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3670 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3671 if err != nil {
3672
3673 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3674 return generateSingleGetValueErrorResponse(err)
3675
3676 }
3677
3678 rxPowerValue := extension.RxPower{}
3679 rxPowerValue.OnuSn = onuDev.serialNumber
3680 rxPowerValue.Status = rxPower.GetStatus()
3681 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3682 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3683
3684 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3685
3686 } else {
3687
3688 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3689 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3690 }
3691
3692 } else {
3693
3694 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
3695 if onuInCache.(*OnuDevice).intfID == ponIntdID {
3696
3697 Onu := oop.Onu{IntfId: ponIntdID, OnuId: onuInCache.(*OnuDevice).onuID}
3698 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3699 if err != nil {
3700 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3701 } else {
3702
3703 rxPowerValue := extension.RxPower{}
3704 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3705 rxPowerValue.Status = rxPower.GetStatus()
3706 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3707 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3708
3709 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3710 }
3711
3712 }
3713 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3714 return true
3715 })
3716 }
3717 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3718 return &resp
3719}
3720
Gamze Abaka85e9a142021-05-26 13:41:39 +00003721func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3722 errResp := func(status extension.GetValueResponse_Status,
3723 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3724 return &extension.SingleGetValueResponse{
3725 Response: &extension.GetValueResponse{
3726 Status: status,
3727 ErrReason: reason,
3728 },
3729 }
3730 }
3731
3732 if err != nil {
3733 if e, ok := status.FromError(err); ok {
3734 switch e.Code() {
3735 case codes.Internal:
3736 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3737 case codes.DeadlineExceeded:
3738 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3739 case codes.Unimplemented:
3740 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3741 case codes.NotFound:
3742 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3743 }
3744 }
3745 }
3746
3747 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3748}
khenaidoo106c61a2021-08-11 18:05:46 -04003749
3750/*
3751Helper functions to communicate with Core
3752*/
3753
3754func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3755 cClient, err := dh.coreClient.GetCoreServiceClient()
3756 if err != nil || cClient == nil {
3757 return nil, err
3758 }
3759 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3760 defer cancel()
3761 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3762}
3763
khenaidoodc2116e2021-10-19 17:33:19 -04003764func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003765 cClient, err := dh.coreClient.GetCoreServiceClient()
3766 if err != nil || cClient == nil {
3767 return nil, err
3768 }
3769 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3770 defer cancel()
3771 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3772}
3773
khenaidoodc2116e2021-10-19 17:33:19 -04003774func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003775 cClient, err := dh.coreClient.GetCoreServiceClient()
3776 if err != nil || cClient == nil {
3777 return err
3778 }
3779 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3780 defer cancel()
3781 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3782 return err
3783}
3784
3785func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3786 cClient, err := dh.coreClient.GetCoreServiceClient()
3787 if err != nil || cClient == nil {
3788 return nil, err
3789 }
3790 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3791 defer cancel()
3792 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3793}
3794
3795func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3796 cClient, err := dh.coreClient.GetCoreServiceClient()
3797 if err != nil || cClient == nil {
3798 return nil, err
3799 }
3800 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3801 defer cancel()
3802 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3803}
3804
3805func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3806 cClient, err := dh.coreClient.GetCoreServiceClient()
3807 if err != nil || cClient == nil {
3808 return err
3809 }
3810 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3811 defer cancel()
3812 _, err = cClient.DeviceUpdate(subCtx, device)
3813 return err
3814}
3815
khenaidoodc2116e2021-10-19 17:33:19 -04003816func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003817 cClient, err := dh.coreClient.GetCoreServiceClient()
3818 if err != nil || cClient == nil {
3819 return nil, err
3820 }
3821 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3822 defer cancel()
3823 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3824}
3825
khenaidoodc2116e2021-10-19 17:33:19 -04003826func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003827 cClient, err := dh.coreClient.GetCoreServiceClient()
3828 if err != nil || cClient == nil {
3829 return err
3830 }
3831 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3832 defer cancel()
3833 _, err = cClient.SendPacketIn(subCtx, pkt)
3834 return err
3835}
3836
3837func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3838 cClient, err := dh.coreClient.GetCoreServiceClient()
3839 if err != nil || cClient == nil {
3840 return err
3841 }
3842 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3843 defer cancel()
3844 _, err = cClient.PortCreated(subCtx, port)
3845 return err
3846}
3847
khenaidoodc2116e2021-10-19 17:33:19 -04003848func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003849 cClient, err := dh.coreClient.GetCoreServiceClient()
3850 if err != nil || cClient == nil {
3851 return err
3852 }
3853 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3854 defer cancel()
3855 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3856 return err
3857}
3858
khenaidoodc2116e2021-10-19 17:33:19 -04003859func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003860 cClient, err := dh.coreClient.GetCoreServiceClient()
3861 if err != nil || cClient == nil {
3862 return err
3863 }
3864 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3865 defer cancel()
3866 _, err = cClient.PortStateUpdate(subCtx, portState)
3867 return err
3868}
3869
khenaidoodc2116e2021-10-19 17:33:19 -04003870func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003871 cClient, err := dh.coreClient.GetCoreServiceClient()
3872 if err != nil || cClient == nil {
3873 return nil, err
3874 }
3875 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3876 defer cancel()
3877 return cClient.GetDevicePort(subCtx, portFilter)
3878}
3879
nikesh.krishnanc8473432023-06-14 12:14:54 +05303880func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
3881 cClient, err := dh.coreClient.GetCoreServiceClient()
3882 if err != nil || cClient == nil {
3883 return nil, err
3884 }
3885 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3886 defer cancel()
3887 return cClient.GetPorts(subCtx, portFilter)
3888}
3889
khenaidoo106c61a2021-08-11 18:05:46 -04003890/*
3891Helper functions to communicate with child adapter
3892*/
3893
khenaidoodc2116e2021-10-19 17:33:19 -04003894func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003895 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3896 if err != nil || aClient == nil {
3897 return err
3898 }
3899 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3900 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3901 defer cancel()
3902 _, err = aClient.OmciIndication(subCtx, response)
3903 return err
3904}
3905
khenaidoodc2116e2021-10-19 17:33:19 -04003906func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003907 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3908 if err != nil || aClient == nil {
3909 return err
3910 }
3911 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3912 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3913 defer cancel()
3914 _, err = aClient.OnuIndication(subCtx, onuInd)
3915 return err
3916}
3917
khenaidoodc2116e2021-10-19 17:33:19 -04003918func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003919 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3920 if err != nil || aClient == nil {
3921 return err
3922 }
3923 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3924 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3925 defer cancel()
3926 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3927 return err
3928}
3929
khenaidoodc2116e2021-10-19 17:33:19 -04003930func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003931 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3932 if err != nil || aClient == nil {
3933 return err
3934 }
3935 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3936 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3937 defer cancel()
3938 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3939 return err
3940}
3941
khenaidoodc2116e2021-10-19 17:33:19 -04003942func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003943 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3944 if err != nil || aClient == nil {
3945 return err
3946 }
3947 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3948 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3949 defer cancel()
3950 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3951 return err
3952}
3953
3954/*
3955Helper functions for remote communication
3956*/
3957
3958// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3959// supports is deleted
3960func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3961 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3962
3963 dh.lockChildAdapterClients.Lock()
3964 defer dh.lockChildAdapterClients.Unlock()
3965 if _, ok := dh.childAdapterClients[endpoint]; ok {
3966 // Already set
3967 return nil
3968 }
3969
3970 // Setup child's adapter grpc connection
3971 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003972 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3973 dh.cfg.AdapterEndpoint,
3974 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003975 "onu_inter_adapter_service.OnuInterAdapterService",
3976 dh.onuInterAdapterRestarted,
3977 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003978 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3979 return err
3980 }
khenaidooefff76e2021-12-15 16:51:30 -05003981 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003982
3983 // Wait until we have a connection to the child adapter.
3984 // Unlimited retries or until context expires
3985 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3986 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3987 for {
3988 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3989 if err == nil && client != nil {
3990 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3991 break
3992 }
3993 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3994 // Backoff
3995 if err = backoff.Backoff(subCtx); err != nil {
3996 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3997 break
3998 }
3999 }
4000 return nil
4001}
4002
khenaidoodc2116e2021-10-19 17:33:19 -04004003func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004004
4005 // First check from cache
4006 dh.lockChildAdapterClients.RLock()
4007 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4008 dh.lockChildAdapterClients.RUnlock()
4009 return cgClient.GetOnuInterAdapterServiceClient()
4010 }
4011 dh.lockChildAdapterClients.RUnlock()
4012
4013 // Set the child connection - can occur on restarts
4014 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4015 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4016 cancel()
4017 if err != nil {
4018 return nil, err
4019 }
4020
4021 // Get the child client now
4022 dh.lockChildAdapterClients.RLock()
4023 defer dh.lockChildAdapterClients.RUnlock()
4024 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4025 return cgClient.GetOnuInterAdapterServiceClient()
4026 }
4027 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4028}
4029
4030func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4031 dh.lockChildAdapterClients.Lock()
4032 defer dh.lockChildAdapterClients.Unlock()
4033 for key, client := range dh.childAdapterClients {
4034 client.Stop(ctx)
4035 delete(dh.childAdapterClients, key)
4036 }
4037}
4038
khenaidooefff76e2021-12-15 16:51:30 -05004039// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4040func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4041 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004042 return nil
4043}
4044
khenaidooefff76e2021-12-15 16:51:30 -05004045// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4046func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4047 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004048 return nil
4049 }
khenaidooefff76e2021-12-15 16:51:30 -05004050 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004051}
Girish Gowdra950326e2021-11-05 12:43:24 -07004052
4053func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4054 dh.lockDevice.Lock()
4055 defer dh.lockDevice.Unlock()
4056 dh.isDeviceDeletionInProgress = flag
4057}
4058
4059func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4060 dh.lockDevice.RLock()
4061 defer dh.lockDevice.RUnlock()
4062 return dh.isDeviceDeletionInProgress
4063}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004064
4065// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4066// Returns false if waiting timed out.
4067func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4068 c := make(chan struct{})
4069 go func() {
4070 defer close(c)
4071 wg.Wait()
4072 }()
4073 select {
4074 case <-c:
4075 return true // completed normally
4076 case <-time.After(timeout):
4077 return false // timed out
4078 }
4079}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304080
4081func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4082 val, err := json.Marshal(signature)
4083 if err != nil {
4084 logger.Error(ctx, "failed-to-marshal")
4085 return
4086 }
4087 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4088 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4089 }
4090}
4091
4092func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4093 var signature uint32
4094
4095 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4096 if er == nil {
4097 if Value != nil {
4098 Val, er := kvstore.ToByte(Value.Value)
4099 if er != nil {
4100 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4101 return signature
4102 }
4103 if er = json.Unmarshal(Val, &signature); er != nil {
4104 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4105 return signature
4106 }
4107 }
4108 }
4109 return signature
4110}