blob: 266439178e949734cbaa41e8121bcc28d22c7828 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002 * Copyright 2018-2024 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
nikesh.krishnand9812542023-08-01 18:31:39 +053049 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
khenaidoo106c61a2021-08-11 18:05:46 -040050 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053051 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080052 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040053 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040054 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040055 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040056 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
57 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040058 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
59 oop "github.com/opencord/voltha-protos/v5/go/openolt"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +053060 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
khenaidoo106c61a2021-08-11 18:05:46 -040061 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070062 "google.golang.org/grpc"
nikesh.krishnand9812542023-08-01 18:31:39 +053063 codes "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040064 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053065)
66
salmansiddiqui7ac62132019-08-22 03:58:50 +000067// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040068const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080069 InvalidPort = 0xffffffff
70 MaxNumOfGroupHandlerChannels = 256
71
72 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
73 McastFlowOrGroupModify = "McastFlowOrGroupModify"
74 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050075 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010076
77 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053078 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040079)
80
Mahir Gunyela2e68702022-12-07 00:00:42 -080081// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053082type DeviceHandler struct {
Akash Kankanala041a2122024-10-16 15:49:22 +053083 EventProxy eventif.EventProxy
84 Client oop.OpenoltClient
85 cm *config.ConfigManager
86 device *voltha.Device
87 cfg *conf.AdapterFlags
88 coreClient *vgrpc.Client
89 childAdapterClients map[string]*vgrpc.Client
90 openOLT *OpenOLT
91 exitChannel chan struct{}
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 groupMgr *OpenOltGroupMgr
95 eventMgr *OpenOltEventMgr
96 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070097
98 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053099
Akash Kankanala041a2122024-10-16 15:49:22 +0530100 portStats *OpenOltStatisticsMgr
101 metrics *pmmetrics.PmMetrics
102 stopCollector chan bool
103 stopHeartbeatCheck chan bool
104 stopIndications chan bool
105 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
106
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700107 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
108 // if the value is true that means the OnuDiscovery indication
109 // is currently being processed and thus we can ignore concurrent requests
110 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
111 // if we do it means something went wrong and we need to retry
Akash Kankanala041a2122024-10-16 15:49:22 +0530112 discOnus sync.Map
113 onus sync.Map
114 activePorts sync.Map
115 flowMgr []*OpenOltFlowMgr
116 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra491a9c62021-01-06 16:43:07 -0800117
118 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
119 // 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 -0700120 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
121 stopMcastHandlerRoutine []chan bool
122 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000123
Akash Kankanala041a2122024-10-16 15:49:22 +0530124 lockChildAdapterClients sync.RWMutex
125 lockDevice sync.RWMutex
126 perPonOnuIndicationChannelLock sync.Mutex
127
128 totalPonPorts uint32
129 heartbeatSignature uint32
130 isCollectorActive bool
131 isHeartbeatCheckActive bool
132 isReadIndicationRoutineActive bool
133
Gamze Abakac2c32a62021-03-11 11:44:18 +0000134 adapterPreviouslyConnected bool
135 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700136
137 isDeviceDeletionInProgress bool
Nandita Biradar1b590f12024-09-27 10:56:28 +0530138 prevOperStatus common.OperStatus_Types
bseenivaaa9165b2025-09-18 17:28:12 +0530139 collectorWaitGroup sync.WaitGroup
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700140}
141
Mahir Gunyela2e68702022-12-07 00:00:42 -0800142// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700143type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400144 deviceID string
145 deviceType string
146 serialNumber string
Akash Kankanala041a2122024-10-16 15:49:22 +0530147 proxyDeviceID string
148 adapterEndpoint string
khenaidoo106c61a2021-08-11 18:05:46 -0400149 onuID uint32
150 intfID uint32
khenaidoo106c61a2021-08-11 18:05:46 -0400151 losRaised bool
152 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700153}
154
Mahir Gunyelb0046752021-02-26 13:51:05 -0800155type onuIndicationMsg struct {
156 ctx context.Context
157 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800158}
159
160type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800161 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800162 stopChannel chan struct{}
163}
164
Mahir Gunyela2e68702022-12-07 00:00:42 -0800165// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
166// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
167// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
168// 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 -0800169type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400170 ctx context.Context // Flow/group handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400171 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
172 group *of.OfpGroupEntry // Group message (can be nil or valid group)
173 errChan *chan error // channel to report the mcast Flow/group handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530174 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
Girish Gowdra491a9c62021-01-06 16:43:07 -0800175}
176
Naga Manjunath7615e552019-10-11 22:35:47 +0530177var pmNames = []string{
178 "rx_bytes",
179 "rx_packets",
180 "rx_mcast_packets",
181 "rx_bcast_packets",
182 "tx_bytes",
183 "tx_packets",
184 "tx_mcast_packets",
185 "tx_bcast_packets",
186}
187
Mahir Gunyela2e68702022-12-07 00:00:42 -0800188// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400189func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700190 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700191 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700192 device.deviceType = deviceTp
193 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700194 device.onuID = onuID
195 device.intfID = intfID
196 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530197 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400198 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700199 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530200}
201
Mahir Gunyela2e68702022-12-07 00:00:42 -0800202// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400203func 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 -0700204 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530205 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800206 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400207 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400208 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700209 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700210 dh.device = cloned
211 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500212 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700213 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000214 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
215 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530216 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 -0500217 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800218 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800219 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400220 dh.childAdapterClients = make(map[string]*vgrpc.Client)
221 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300222 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530223 if dh.kvStore == nil {
224 logger.Error(ctx, "Failed to setup KV store")
225 return nil
226 }
227
Girish Gowdra491a9c62021-01-06 16:43:07 -0800228 // Create a slice of buffered channels for handling concurrent mcast flow/group.
229 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700230 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
231 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800232 for i := range dh.incomingMcastFlowOrGroup {
233 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800234 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800235 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
236 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
237 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
238 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700239 dh.mcastHandlerRoutineActive[i] = true
240 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800241 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530242 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700243 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530244}
245
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530246func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
247 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
248 switch storeType {
249 case "etcd":
250 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530251 case "redis":
252 return kvstore.NewRedisClient(address, timeout, false)
253 case "redis-sentinel":
254 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530255 }
256 return nil, errors.New("unsupported-kv-store")
257}
258
259// SetKVClient sets the KV client and return a kv backend
260func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
261 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
262 if err != nil {
263 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
264 return nil
265 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530266 kvbackend := &db.Backend{
267 Client: kvClient,
268 StoreType: backend,
269 Address: addr,
270 Timeout: rsrcMgr.KvstoreTimeout,
271 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
272
273 return kvbackend
274}
275
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000276// CloseKVClient closes open KV clients
277func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
278 if dh.resourceMgr != nil {
279 for _, rscMgr := range dh.resourceMgr {
280 if rscMgr != nil {
281 rscMgr.CloseKVClient(ctx)
282 }
283 }
284 }
285 if dh.flowMgr != nil {
286 for _, flMgr := range dh.flowMgr {
287 if flMgr != nil {
288 flMgr.CloseKVClient(ctx)
289 }
290 }
291 }
292}
293
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530294// start save the device to the data model
295func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700296 dh.lockDevice.Lock()
297 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000298 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700299 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000300 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530301}
302
khenaidooefff76e2021-12-15 16:51:30 -0500303// Stop stops the device handler
304func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700305 dh.lockDevice.Lock()
306 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000307 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500308 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400309
khenaidooefff76e2021-12-15 16:51:30 -0500310 // Delete (which will stop also) all grpc connections to the child adapters
311 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530313}
314
ssiddiqui04386ee2021-08-23 21:58:25 +0530315func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
316 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
317 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
318 if pooledIntfID == intfID {
319 return resourceRanges.GetTechnology()
320 }
321 }
322 }
323 return ""
324}
325
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400326func macifyIP(ip net.IP) string {
327 if len(ip) > 0 {
328 oct1 := strconv.FormatInt(int64(ip[12]), 16)
329 oct2 := strconv.FormatInt(int64(ip[13]), 16)
330 oct3 := strconv.FormatInt(int64(ip[14]), 16)
331 oct4 := strconv.FormatInt(int64(ip[15]), 16)
332 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
333 }
334 return ""
335}
336
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400338 var genmac string
339 var addr net.IP
340 var ips []string
341 var err error
342
Neha Sharma96b7bf22020-06-15 10:37:32 +0000343 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400344
345 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000346 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400347
348 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000349 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400350 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000351 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400352 }
353 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530355 log.Fields{"host": ips[0],
356 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400357 return genmac, nil
358 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000359 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400360 }
361
362 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000363 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530364 log.Fields{"host": host,
365 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400366 return genmac, nil
367}
368
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530369func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700370 slist := strings.Split(mac, ":")
371 result := make([]uint32, len(slist))
372 var err error
373 var tmp int64
374 for index, val := range slist {
375 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
376 return []uint32{1, 2, 3, 4, 5, 6}
377 }
378 result[index] = uint32(tmp)
379 }
380 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530381}
382
Mahir Gunyela2e68702022-12-07 00:00:42 -0800383// 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 -0800384func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800385 switch portType {
386 case voltha.Port_ETHERNET_NNI:
387 return fmt.Sprintf("nni-%d", portNum), nil
388 case voltha.Port_PON_OLT:
389 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700390 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800391
Girish Kumarf26e4882020-03-05 06:49:10 +0000392 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530393}
394
Elia Battiston596406d2022-02-02 12:19:00 +0100395func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
396 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530397 // In case it was not set in the indication
398 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100399 speedMbps = defaultPortSpeedMbps
400 }
401
402 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
403 switch speedMbps {
404 case 1000000:
405 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
406 case 100000:
407 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
408 case 40000:
409 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
410 case 10000:
411 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
412 case 1000:
413 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
414 case 100:
415 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
416 case 10:
417 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
418 }
419
420 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
421
422 port := &of.OfpPort{
423 HwAddr: macAddressToUint32Array(macAddress),
424 Config: 0,
425 State: uint32(of.OfpPortState_OFPPS_LIVE),
426 Curr: capacity,
427 Advertised: capacity,
428 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530429 CurrSpeed: speedMbps * 1000, // kbps
430 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100431 }
432
433 return port
434}
435
436func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000437 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700438 if state == "up" {
439 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530440 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500441 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700442 } else {
443 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500444 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700445 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700446 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400447 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800448 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000449 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400450 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500451
khenaidoo106c61a2021-08-11 18:05:46 -0400452 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400453 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400454 DeviceId: dh.device.Id,
455 Port: portNum,
456 })
457 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000458 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400459 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400460 DeviceId: dh.device.Id,
461 PortType: portType,
462 PortNo: portNum,
463 OperStatus: operStatus})
464 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400465 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
466 "device-id": dh.device.Id,
467 "port-type": portType,
468 "port-number": portNum,
469 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500470 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400471 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500472 }
khenaidoo106c61a2021-08-11 18:05:46 -0400473
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400474 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400475 port = &voltha.Port{
476 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700477 PortNo: portNum,
478 Label: label,
479 Type: portType,
480 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100481 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700482 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000483 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400485 err = dh.createPortInCore(ctx, port)
486 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000487 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800488 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000489 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400490 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000491 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530492 return nil
493}
494
Kent Hagermane6ff1012020-07-14 15:07:53 -0400495func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400496 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530497 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400498 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
499 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530500 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800501 dh.lockDevice.Lock()
502 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530503 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530504}
505
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700506// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530507// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800508func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000509 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700510 defer func() {
511 dh.lockDevice.Lock()
512 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530513 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700514 dh.lockDevice.Unlock()
515 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700516 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700517 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700518 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700519 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400520
David Bainbridgef5879ca2019-12-13 21:17:54 +0000521 // Create an exponential backoff around re-enabling indications. The
522 // maximum elapsed time for the back off is set to 0 so that we will
523 // continue to retry. The max interval defaults to 1m, but is set
524 // here for code clarity
525 indicationBackoff := backoff.NewExponentialBackOff()
526 indicationBackoff.MaxElapsedTime = 0
527 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700528
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700529 dh.lockDevice.Lock()
530 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530531 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700532 dh.lockDevice.Unlock()
533
Girish Gowdra3f974912020-03-23 20:35:18 -0700534Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700535 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400536 select {
537 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000538 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700539 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400540 default:
541 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100542
543 select {
544 case <-indications.Context().Done():
545 if err != nil {
546 logger.Warnw(ctx, "error-during-enable-indications",
547 log.Fields{"err": err,
548 "device-id": dh.device.Id})
549 }
550
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400551 // Use an exponential back off to prevent getting into a tight loop
552 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100553 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
554 "device-id": dh.device.Id,
555 "duration": duration,
556 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400557 if duration == backoff.Stop {
558 // If we reach a maximum then warn and reset the backoff
559 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100560 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530561 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530562 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400563 indicationBackoff.Reset()
564 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700565
566 // On failure process a backoff timer while watching for stopIndications
567 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700568 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700569 select {
570 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000571 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700572 if !backoffTimer.Stop() {
573 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700574 }
575 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700576 case <-backoffTimer.C:
577 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700578 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700579 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
580 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400581 }
582 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100583 default:
584 if err != nil {
585 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530586 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530587 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100588 // Close the stream, and re-initialize it
589 if err = indications.CloseSend(); err != nil {
590 // Ok to ignore here, because we landed here due to a problem on the stream
591 // In all probability, the closeSend call may fail
592 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
593 log.Fields{"err": err,
594 "device-id": dh.device.Id})
595 }
596 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
597 return err
598 }
599 // once we re-initialized the indication stream, continue to read indications
600 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700601 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100602 // Reset backoff if we have a successful receive
603 indicationBackoff.Reset()
604 // When OLT is admin down, ignore all indications.
605 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
606 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
607 log.Fields{"indication": indication,
608 "device-id": dh.device.Id})
609 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700610 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100611 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530612 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700613 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700615 // Close the send stream
616 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700617
Girish Gowdra3f974912020-03-23 20:35:18 -0700618 return nil
619}
620
621func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700622 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700623 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
624 if err != nil {
625 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
626 }
627 if indications == nil {
628 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
629 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700630 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700631 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400632}
633
634// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
635func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
636 switch indication.Data.(type) {
637 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
638 return true
639
640 default:
641 return false
642 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643}
644
David K. Bainbridge794735f2020-02-11 21:01:37 -0800645func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700646 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000647 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530648 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530650 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000652 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000653 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530654 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000655 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800656 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000657 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800658 }
659 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700660}
661
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530662func (dh *DeviceHandler) handleOnuDisableIndication(ctx context.Context, onuIndication *oop.OnuDisabledIndication) error {
663 logger.Infow(ctx, "handleOnuDisableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
664 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
665 intfID := onuIndication.GetIntfId()
666 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
667 onuDev := dh.getChildDevice(ctx, sn, ponPort)
668 if onuDev == nil {
669 logger.Warnw(ctx, "handleOnuDisableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
670 onuDev = &OnuDevice{
671 serialNumber: sn,
672 }
673 }
674 dh.discOnus.Delete(sn)
675
676 raisedTs := time.Now().Unix()
677 if err := dh.eventMgr.onuDisableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
678 return olterrors.NewErrAdapter("failed-indication", log.Fields{
679 "device-id": dh.device.Id,
680 "indication": onuIndication,
681 "timestamp": raisedTs}, err)
682 }
683 OnuIndication := generateOnuIndication(onuDev.intfID, onuDev.onuID, "down", "down")
684 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDev.adapterEndpoint, &ia.OnuIndicationMessage{
685 DeviceId: onuDev.deviceID,
686 OnuIndication: OnuIndication.GetOnuInd(),
687 })
688 if err != nil {
689 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
690 "onu-indicator": OnuIndication.GetOnuInd(),
691 "source": dh.openOLT.config.AdapterEndpoint,
692 "device-type": onuDev.deviceType,
693 "device-id": onuDev.deviceID}, err)
694 }
695 return nil
696}
697
698func (dh *DeviceHandler) handleOnuEnableIndication(ctx context.Context, onuIndication *oop.OnuEnabledIndication) error {
699 logger.Infow(ctx, "handleOnuEnableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
700 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
701 intfID := onuIndication.GetIntfId()
702 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
703 onuDev := dh.getChildDevice(ctx, sn, ponPort)
704 if onuDev == nil {
705 logger.Warnw(ctx, "handleOnuEnableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
706 onuDev = &OnuDevice{
707 serialNumber: sn,
708 }
709 }
710 raisedTs := time.Now().Unix()
711
712 if err := dh.eventMgr.onuEnableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
713 return olterrors.NewErrAdapter("failed-indication", log.Fields{
714 "device-id": dh.device.Id,
715 "indication": onuIndication,
716 "timestamp": raisedTs}, err)
717 }
718 return nil
719}
720
Akash Kankanala041a2122024-10-16 15:49:22 +0530721// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530722func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700723 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 switch indication.Data.(type) {
725 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000726 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
727 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700728 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 -0800729 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400730 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800731 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000733 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
734 defer span.Finish()
735
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800737 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100738 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400739 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800740 }
741 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000742 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700743 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000744 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
745 defer span.Finish()
746
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 intfOperInd := indication.GetIntfOperInd()
748 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800749 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100750 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400751 _ = 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 -0800752 }
753 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700754 } else if intfOperInd.GetType() == "pon" {
755 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
756 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800757 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100758 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400759 _ = 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 -0800760 }
761 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000762 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700763 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000764 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530765 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530766 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000768 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
769 defer span.Finish()
770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700771 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530773 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800774 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700775 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000776 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
777 defer span.Finish()
778
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000780 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530781 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800782 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700783 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000784 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
785 defer span.Finish()
786
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700787 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000788 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 -0800789 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000790 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400791 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800792 }
793 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700794 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000795 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
796 defer span.Finish()
797
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700798 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000799 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700800 "intf-type": pktInd.IntfId,
801 "intf-id": pktInd.IntfId,
802 "gem-port-id": pktInd.GemportId,
803 "port-no": pktInd.PortNo,
804 "device-id": dh.device.Id,
805 })
806
807 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700809 "intf-type": pktInd.IntfId,
810 "intf-id": pktInd.IntfId,
811 "gem-port-id": pktInd.GemportId,
812 "port-no": pktInd.PortNo,
813 "packet": hex.EncodeToString(pktInd.Pkt),
814 "device-id": dh.device.Id,
815 })
816 }
817
David K. Bainbridge794735f2020-02-11 21:01:37 -0800818 go func() {
819 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400820 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800821 }
822 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700823 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000824 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
825 defer span.Finish()
826
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700827 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700828 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000830 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
831 defer span.Finish()
832
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700833 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700835 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000836 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
837 defer span.Finish()
838
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
841 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530842 case *oop.Indication_OnuDisabledInd:
843 span, ctx := log.CreateChildSpan(ctx, "onu-disable-indication", log.Fields{"device-id": dh.device.Id})
844 defer span.Finish()
845 logger.Infow(ctx, "received onu-disable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
846 if err := dh.handleOnuDisableIndication(ctx, indication.GetOnuDisabledInd()); err != nil {
847 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
848 }
849 case *oop.Indication_OnuEnabledInd:
850 span, ctx := log.CreateChildSpan(ctx, "onu-enable-indication", log.Fields{"device-id": dh.device.Id})
851 defer span.Finish()
852 logger.Infow(ctx, "received onu-enable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
853 if err := dh.handleOnuEnableIndication(ctx, indication.GetOnuEnabledInd()); err != nil {
854 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
855 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700856 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530857}
858
nikesh.krishnanc8473432023-06-14 12:14:54 +0530859func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
860 onuInd := &oop.OnuIndication{
861 IntfId: intfID,
862 OnuId: onuID,
863 OperState: operState,
864 AdminState: adminState,
865 }
866 indication := &oop.Indication{
867 Data: &oop.Indication_OnuInd{
868 OnuInd: onuInd,
869 },
870 }
871 return indication
872}
873
874func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
875 onuAlarmInd := &oop.OnuAlarmIndication{
876 IntfId: intfID,
877 OnuId: onuID,
878 LosStatus: losStatus,
879 }
880 alarmInd := &oop.AlarmIndication{
881 Data: &oop.AlarmIndication_OnuAlarmInd{
882 OnuAlarmInd: onuAlarmInd,
883 },
884 }
885 return alarmInd
886}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530887
Akash Kankanala041a2122024-10-16 15:49:22 +0530888func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530889 ponlosAlarmInd := &oop.LosIndication{
890 IntfId: intfID,
891 Status: losStatus,
892 }
893 alarmInd := &oop.AlarmIndication{
894 Data: &oop.AlarmIndication_LosInd{
895 LosInd: ponlosAlarmInd,
896 },
897 }
898 return alarmInd
899}
Akash Kankanala041a2122024-10-16 15:49:22 +0530900
nikesh.krishnanc8473432023-06-14 12:14:54 +0530901func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
902 go func() {
903 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
904 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
905 }
906 }()
907
908 raisedTs := time.Now().Unix()
909 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
910}
911
912func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530913 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
914 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530915 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530916 return err
917 }
918 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530919 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
920 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
921 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
922
923 onuID := onuDeviceFromCore.ProxyAddress.OnuId
924 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
925 if err != nil {
926 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530927 } else {
928 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
929 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
930 switch {
931 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
932 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
933 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
934
935 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530936 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530937 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
938 raisedTs := time.Now().Unix()
939 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
940
941 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
942 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530943 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530944 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530945 return nil
946}
947
948func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
949 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
950 DeviceId: dh.device.Id,
951 PortType: voltha.Port_PON_OLT,
952 })
953 if err != nil {
954 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530955 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530956 }
957 for _, portFromCore := range portsFromCore.Items {
958 portNum := portFromCore.GetPortNo()
959 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
960 portOperStatusFromCore := portFromCore.OperStatus
961 portAdminStateFromCore := portFromCore.AdminState
962 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
963 if err != nil {
964 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
965 } else {
966 portLosFromOlt := ponPortFromOlt.GetLos()
967 portStateFromOlt := ponPortFromOlt.GetState()
968 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
969 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
970 "portStateFromOlt": portStateFromOlt.String(),
971 "portOperStatusFromCore": portOperStatusFromCore.String(),
972 "device-id": dh.device.Id,
973 "port": portNum})
974 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
975 raisedTs := time.Now().Unix()
976 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530977 }
978 switch {
979 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
980 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
981 "portStateFromOlt": portStateFromOlt.String(),
982 "portOperStatusFromCore": portOperStatusFromCore.String(),
983 "device-id": dh.device.Id,
984 "port": portNum})
985 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
986 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
987 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
988 "portStateFromOlt": portStateFromOlt.String(),
989 "portOperStatusFromCore": portOperStatusFromCore.String(),
990 "device-id": dh.device.Id,
991 "port": portNum})
992 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
993 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
994 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
995 "device-id": dh.device.Id,
996 "port": portNum})
997 default:
998 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
999 "portStateFromOlt": portStateFromOlt.String(),
1000 "portOperStatusFromCore": portOperStatusFromCore.String(),
1001 "device-id": dh.device.Id,
1002 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301003 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301004 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301005 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301006 return nil
1007}
1008
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301009// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301010func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +05301011 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +05301012 // Declare deviceStateFilter to be used later
1013 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +05301014 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001015 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +05301016 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301017 if err != nil {
1018 return fmt.Errorf("failed to get device from core: %w", err)
1019 }
1020 logger.Info(ctx, "Device state", log.Fields{
1021 "device-id": device.Id,
1022 "CurrOperStatus": device.OperStatus,
1023 "CurrConnStatus": device.ConnectStatus,
1024 })
1025 // Perform cleanup if the device's operational status is REBOOTED
1026 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
1027 // Log the device's operational status if it's REBOOTED
1028 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
1029 "device-id": device.Id,
1030 "OperStatus": device.OperStatus,
1031 })
1032 dh.lockDevice.RLock()
1033 // Stop the read indication only if it the routine is active
1034 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1035 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1036 // on next execution of the readIndication routine.
1037 if dh.isHeartbeatCheckActive {
1038 dh.stopHeartbeatCheck <- true
1039 }
1040 if dh.isReadIndicationRoutineActive {
1041 dh.stopIndications <- true
1042 }
bseenivaaa9165b2025-09-18 17:28:12 +05301043 if dh.isCollectorActive {
1044 dh.stopCollector <- true
1045 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301046 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +05301047 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301048 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
1049 return fmt.Errorf("cleanup device resources failed: %w", err)
1050 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301051 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301052 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1053 }
bseenivaaa9165b2025-09-18 17:28:12 +05301054 dh.collectorWaitGroup.Add(1)
1055 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301056 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301057 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +05301058 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
1059 // Log the device's operational status if it's RECONCILING
1060 logger.Info(ctx, "Device is being reconciled", log.Fields{
1061 "device-id": device.Id,
1062 "OperStatus": device.OperStatus,
1063 })
1064
1065 // Perform reconciliation steps
1066 err = dh.reconcileOnus(ctx)
1067 if err != nil {
1068 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1069 }
1070 err = dh.reconcilePonPorts(ctx)
1071 if err != nil {
1072 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301073 }
1074 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001075 // instantiate the mcast handler routines.
1076 for i := range dh.incomingMcastFlowOrGroup {
1077 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1078 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1079 if !dh.mcastHandlerRoutineActive[i] {
1080 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1081 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1082 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1083 // for incoming mcast flow/group to be processed serially.
1084 dh.mcastHandlerRoutineActive[i] = true
1085 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1086 }
1087 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301088 // Create DeviceStateFilter with the desired operational and connection statuses
1089 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001090 DeviceId: dh.device.Id,
1091 OperStatus: voltha.OperStatus_ACTIVE,
1092 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301093 }
1094 // Log DeviceStateFilter for debugging purposes
1095 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1096 "DeviceId": deviceStateFilter.DeviceId,
1097 "OperStatus": deviceStateFilter.OperStatus,
1098 "ConnStatus": deviceStateFilter.ConnStatus,
1099 })
1100 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301101 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001102 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001103 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001104
Akash Kankanala041a2122024-10-16 15:49:22 +05301105 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001106 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1107 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301108
1109 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1110 if err != nil {
1111 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1112 }
1113 dh.populateActivePorts(ctx, ports.Items)
1114 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1115 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1116 }
1117
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001118 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001119 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1120
Girish Gowdru0c588b22019-04-23 23:24:56 -04001121 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301122}
1123
1124// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301125func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001126 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001127
khenaidoo106c61a2021-08-11 18:05:46 -04001128 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001129 if err != nil || device == nil {
1130 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001131 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001132 }
1133
1134 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001135
Akash Kankanala041a2122024-10-16 15:49:22 +05301136 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001137 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001138 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001139 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001140 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001141
khenaidoodc2116e2021-10-19 17:33:19 -04001142 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001143 DeviceId: cloned.Id,
1144 OperStatus: cloned.OperStatus,
1145 ConnStatus: cloned.ConnectStatus,
1146 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001147 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001148 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001149
Akash Kankanala041a2122024-10-16 15:49:22 +05301150 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001151 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001152 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001153 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001154 }
1155 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001156 // Update onu state as down in onu adapter
1157 onuInd := oop.OnuIndication{}
1158 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001159
1160 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1161 if err != nil {
1162 return err
1163 }
1164 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001165 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001166 DeviceId: onuDevice.Id,
1167 OnuIndication: &onuInd,
1168 })
1169 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001171 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001172 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 "onu-indicator": onuInd,
1174 "device-type": onuDevice.Type,
1175 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301176 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001177 } else {
1178 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 -07001179 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001180 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001181 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001182 /* Discovered ONUs entries need to be cleared , since after OLT
1183 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301184 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001185 dh.lockDevice.Unlock()
1186
Neha Sharma96b7bf22020-06-15 10:37:32 +00001187 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001188 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301189}
1190
1191// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301192func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001193 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001194
1195 // if the connection is already available, close the previous connection (olt reboot case)
1196 if dh.clientCon != nil {
1197 if err = dh.clientCon.Close(); err != nil {
1198 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1199 } else {
1200 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1201 }
1202 }
1203
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301204 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001205 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001206 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1207 grpc.WithInsecure(),
1208 grpc.WithBlock(),
1209 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001210 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001211 )),
1212 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001213 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001214 )))
1215
1216 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301217 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301218 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001219 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001220 }
Akash Sonif49299a2024-04-25 12:06:37 +05301221 //Setting oper and connection state to RECONCILING and conn state to reachable
1222 cgClient, err := dh.coreClient.GetCoreServiceClient()
1223 if err != nil {
1224 return err
1225 }
1226
1227 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1228 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1229 defer cancel()
1230 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1231 DeviceId: dh.device.Id,
1232 OperStatus: voltha.OperStatus_RECONCILING,
1233 ConnStatus: voltha.ConnectStatus_REACHABLE,
1234 }); err != nil {
1235 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1236 }
1237 // The OperState and connection state of the device is set to RECONCILING and REACHABLE in the previous section. This also needs to be set on the
1238 // locally cached copy of the device struct.
1239 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1240 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1241 }
1242
Girish Gowdru0c588b22019-04-23 23:24:56 -04001243 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301244}
1245
1246// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301247func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001248 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301249 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001250 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301251}
1252
1253// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301254func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301255 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001256 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001257
1258 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001259 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301260 if err != nil || device == nil {
1261 /*TODO: needs to handle error scenarios */
1262 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1263 }
1264 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001266
1267 cloned := proto.Clone(device).(*voltha.Device)
1268 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1269 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1270 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001271
khenaidoodc2116e2021-10-19 17:33:19 -04001272 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001273 DeviceId: cloned.Id,
1274 OperStatus: cloned.OperStatus,
1275 ConnStatus: cloned.ConnectStatus,
1276 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301277 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 -04001278 }
1279
Chaitrashree G S44124192019-08-07 20:21:36 -04001280 // 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 +05301281 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001282 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301283 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001284 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001285 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1286 // all the modules initialized and ready to handle incoming ONUs.
1287
Thomas Lee S985938d2020-05-04 11:40:41 +05301288 err = dh.initializeDeviceHandlerModules(ctx)
1289 if err != nil {
1290 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 -04001291 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001292
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001293 go startHeartbeatCheck(ctx, dh)
1294
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001295 return nil
1296 }
1297
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001298 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301299 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 -04001300 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301301
Neha Sharma96b7bf22020-06-15 10:37:32 +00001302 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001303
1304 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001305 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001306 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001307
1308 go startHeartbeatCheck(ctx, dh)
1309
cuilin20187b2a8c32019-03-26 19:52:28 -07001310 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301311}
1312
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001313func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001314 var err error
1315 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001316
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001317 if dh.flowMgr != nil {
1318 dh.StopAllFlowRoutines(ctx)
1319 }
1320
1321 dh.CloseKVClient(ctx)
1322
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001323 if err != nil {
1324 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1325 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001326 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1327 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301328 // If collector go routine is active, wait for it to stop
1329 dh.lockDevice.RLock()
1330 if dh.isCollectorActive {
1331 dh.lockDevice.RUnlock()
1332 dh.collectorWaitGroup.Wait()
1333 } else {
1334 dh.lockDevice.RUnlock()
1335 }
yasin saplid0566272021-12-21 09:10:30 +00001336 // +1 is for NNI
1337 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1338 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001339 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001340 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1341 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1342 // There is only one NNI manager since multiple NNI is not supported for now
1343 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001344 // Instantiate resource manager
1345 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 -07001346 return olterrors.ErrResourceManagerInstantiating
1347 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001348 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001349 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1350 // the KV store to manage mcast group data. Provide the first instance (0th index)
1351 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1352 return olterrors.ErrGroupManagerInstantiating
1353 }
yasin saplid0566272021-12-21 09:10:30 +00001354 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001355 // Instantiate flow manager
1356 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301357 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001358 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1359 } else {
1360 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001361 }
1362 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001363 /* TODO: Instantiate Alarm , stats , BW managers */
1364 /* Instantiating Event Manager to handle Alarms and KPIs */
1365 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1366
1367 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001368 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001369
1370 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001371}
1372
Neha Sharma96b7bf22020-06-15 10:37:32 +00001373func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001374 var err error
1375 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301376 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001377
Neha Sharma8f4e4322020-08-06 10:51:53 +00001378 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001379
1380 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001381 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001382 }
1383 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001384 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001385 }
1386
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001388 dh.device.Root = true
1389 dh.device.Vendor = deviceInfo.Vendor
1390 dh.device.Model = deviceInfo.Model
1391 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1392 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1393 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1394
1395 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001396 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001397 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301398 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001399 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001400 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001401 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001402 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001403 dh.device.MacAddress = genmac
1404 } else {
1405 dh.device.MacAddress = deviceInfo.DeviceId
1406 }
1407
1408 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001409 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001410 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001411 }
1412
1413 return deviceInfo, nil
1414}
1415
Neha Sharma96b7bf22020-06-15 10:37:32 +00001416func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301417 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001418
1419 defer func() {
1420 dh.lockDevice.Lock()
1421 dh.isCollectorActive = false
1422 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301423 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001424 }()
1425
1426 dh.lockDevice.Lock()
1427 dh.isCollectorActive = true
1428 dh.lockDevice.Unlock()
1429
Naga Manjunath7615e552019-10-11 22:35:47 +05301430 for {
1431 select {
1432 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301433 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301434 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001435 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001436
khenaidoo106c61a2021-08-11 18:05:46 -04001437 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001438 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001439 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001440 continue
1441 }
khenaidoo106c61a2021-08-11 18:05:46 -04001442 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301443 // NNI Stats
1444 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001445 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301446 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001447 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001448 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001449 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301450 }
1451 // PON Stats
1452 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001453 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301454 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1455 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001456 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001457 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301458 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001459 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001460
yasin sapli9e4c5092022-02-01 13:52:33 +00001461 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001462 if len(onuGemInfoLst) > 0 {
1463 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001464 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001465 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301466 }
1467 }
1468 }
1469}
1470
Mahir Gunyela2e68702022-12-07 00:00:42 -08001471// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301472func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001473 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001474 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301475 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301476
1477 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001478 cgClient, err := dh.coreClient.GetCoreServiceClient()
1479 if err != nil {
1480 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1481 return
1482 }
1483
1484 // Now, set the initial PM configuration for that device
1485 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001486 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301487 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301488}
1489
Mahir Gunyela2e68702022-12-07 00:00:42 -08001490// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001491func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1492 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001493 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301494 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001495 HwDesc: "open_pon",
1496 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001497 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001498 },
1499 SwitchFeatures: &of.OfpSwitchFeatures{
1500 NBuffers: 256,
1501 NTables: 2,
1502 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1503 of.OfpCapabilities_OFPC_TABLE_STATS |
1504 of.OfpCapabilities_OFPC_PORT_STATS |
1505 of.OfpCapabilities_OFPC_GROUP_STATS),
1506 },
1507 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301508}
1509
khenaidoo106c61a2021-08-11 18:05:46 -04001510// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001511func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001512 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001513 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001514 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001515 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001516 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1517 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()
1518 }
khenaidoo106c61a2021-08-11 18:05:46 -04001519 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001520}
1521
Neha Sharma96b7bf22020-06-15 10:37:32 +00001522func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001523 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 -07001524 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001525 var deviceID string
1526 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001527 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001528
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001529 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001530 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001531 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 -07001532 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1533 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001534
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001535 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301536
1537 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001538 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 -07001539 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001540
khenaidoodc2116e2021-10-19 17:33:19 -04001541 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001542 ParentId: dh.device.Id,
1543 OnuId: omciInd.OnuId,
1544 ParentPortNo: ponPort,
1545 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001546 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301547 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001548 "intf-id": omciInd.IntfId,
1549 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001550 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001551 deviceType = onuDevice.Type
1552 deviceID = onuDevice.Id
1553 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001554 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301555 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001556 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001557 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301558 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001559 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 +05301560 deviceType = onuInCache.(*OnuDevice).deviceType
1561 deviceID = onuInCache.(*OnuDevice).deviceID
1562 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001563 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001564 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001565
khenaidoodc2116e2021-10-19 17:33:19 -04001566 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001567 ParentDeviceId: proxyDeviceID,
1568 ChildDeviceId: deviceID,
1569 Message: omciInd.Pkt,
1570 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301571 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001572 "source": dh.openOLT.config.AdapterEndpoint,
1573 "device-type": deviceType,
1574 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001576 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001577 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001578 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301579}
1580
khenaidoo106c61a2021-08-11 18:05:46 -04001581// //ProcessInterAdapterMessage sends the proxied messages to the target device
1582// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1583// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001584// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001585// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001586// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001587// return dh.handleInterAdapterOmciMsg(ctx, msg)
1588// }
1589// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1590// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001591
kesavandb9f54fd2021-11-25 20:08:04 +05301592// ProxyOmciRequests sends the proxied OMCI message to the target device
1593func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301594 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1595 return status.Error(codes.Unavailable, "OLT unreachable")
1596 }
kesavandb9f54fd2021-11-25 20:08:04 +05301597 if omciMsgs.GetProxyAddress() == nil {
1598 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1599 if err != nil {
1600 return olterrors.NewErrNotFound("onu", log.Fields{
1601 "parent-device-id": dh.device.Id,
1602 "child-device-id": omciMsgs.ChildDeviceId}, err)
1603 }
1604 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1605 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1606 return olterrors.NewErrCommunication("send-failed", log.Fields{
1607 "parent-device-id": dh.device.Id,
1608 "child-device-id": omciMsgs.ChildDeviceId}, err)
1609 }
1610 } else {
1611 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1612 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1613 return olterrors.NewErrCommunication("send-failed", log.Fields{
1614 "parent-device-id": dh.device.Id,
1615 "child-device-id": omciMsgs.ChildDeviceId}, err)
1616 }
1617 }
1618 return nil
1619}
1620
1621func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1622 var intfID uint32
1623 var onuID uint32
1624 var connectStatus common.ConnectStatus_Types
1625 if onuDevice != nil {
1626 intfID = onuDevice.ProxyAddress.GetChannelId()
1627 onuID = onuDevice.ProxyAddress.GetOnuId()
1628 connectStatus = onuDevice.ConnectStatus
1629 } else {
1630 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1631 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1632 connectStatus = omciMsgs.GetConnectStatus()
1633 }
1634 if connectStatus != voltha.ConnectStatus_REACHABLE {
1635 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1636
1637 return olterrors.NewErrCommunication("unreachable", log.Fields{
1638 "intf-id": intfID,
1639 "onu-id": onuID}, nil)
1640 }
1641
1642 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1643 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1644
1645 onuSecOmciMsgList := omciMsgs.GetMessages()
1646
1647 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301648 var omciMessage *oop.OmciMsg
1649 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1650 hex.Encode(hexPkt, onuSecOmciMsg)
1651 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1652
1653 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1654 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1655 //https://jira.opencord.org/browse/VOL-4604
1656 transid := extractOmciTransactionID(onuSecOmciMsg)
1657 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1658 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1659
1660 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1661 if err != nil {
1662 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1663 "intf-id": intfID,
1664 "onu-id": onuID,
1665 "message": omciMessage}, err)
1666 }
1667 }
1668 return nil
1669}
1670
khenaidoo106c61a2021-08-11 18:05:46 -04001671// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001672func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001673 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 -07001674
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301675 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1676 return status.Error(codes.Unavailable, "OLT unreachable")
1677 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001678 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001679 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001680 if err != nil {
1681 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001682 "parent-device-id": dh.device.Id,
1683 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001684 }
khenaidoo106c61a2021-08-11 18:05:46 -04001685 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1686 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001687 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001688 "parent-device-id": dh.device.Id,
1689 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001690 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001691 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001692 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1693 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001694 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001695 "parent-device-id": dh.device.Id,
1696 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001697 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001698 }
1699 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301700}
1701
khenaidoodc2116e2021-10-19 17:33:19 -04001702func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001703 var intfID uint32
1704 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001705 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001706 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001707 intfID = onuDevice.ProxyAddress.GetChannelId()
1708 onuID = onuDevice.ProxyAddress.GetOnuId()
1709 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001710 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001711 intfID = omciMsg.GetProxyAddress().GetChannelId()
1712 onuID = omciMsg.GetProxyAddress().GetOnuId()
1713 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001714 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001715 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001716 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 -08001717
Thomas Lee S94109f12020-03-03 16:39:29 +05301718 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001719 "intf-id": intfID,
1720 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001721 }
1722
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001723 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1724 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301725 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001726 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001727 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1728 hex.Encode(hexPkt, omciMsg.Message)
1729 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1730
1731 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1732 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1733 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001734 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001735 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001736
Neha Sharma8f4e4322020-08-06 10:51:53 +00001737 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001738 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301739 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001740 "intf-id": intfID,
1741 "onu-id": onuID,
1742 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001743 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001744 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001745}
1746
David K. Bainbridge794735f2020-02-11 21:01:37 -08001747func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301748 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 +00001749 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001750 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001751 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001752 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301753 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301754 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001755 st, _ := status.FromError(err)
1756 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001757 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001758 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301759 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001760 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001761 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001763 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001764 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001765}
1766
Mahir Gunyela2e68702022-12-07 00:00:42 -08001767// getChildDevice function can be used in general to get child device, if not found in cache the function will
1768// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301769func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1770 var InCacheOnuDev *OnuDevice
1771 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1772 if onuInCache.(*OnuDevice).serialNumber == sn {
1773 InCacheOnuDev = onuInCache.(*OnuDevice)
1774 return false
1775 }
1776 return true
1777 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301778 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301779 if InCacheOnuDev != nil {
1780 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1781 return InCacheOnuDev
1782 }
1783 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1784 ParentId: dh.device.Id,
1785 SerialNumber: sn,
1786 ParentPortNo: parentPortNo,
1787 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301788 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301789 if onuDevice == nil {
1790 return nil
1791 }
1792 onuID := onuDevice.ProxyAddress.OnuId
1793 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1794 onuKey := dh.formOnuKey(intfID, onuID)
1795
1796 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1797 dh.onus.Store(onuKey, onuDev)
1798 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1799 return onuDev
1800}
1801
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301802// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1803// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301804func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001805 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301806 // CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301807 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301808 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1809 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1810 ParentId: dh.device.Id,
1811 SerialNumber: sn,
1812 ParentPortNo: parentPortNo,
1813 })
1814 if onuDevice != nil {
1815 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1816 return true, nil
1817 }
1818 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1819
1820 return false, nil
1821 } else {
1822 tpInstExists := false
1823 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301824 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1825 if onuDev != nil {
1826 var onuGemInfo *rsrcMgr.OnuGemInfo
1827 var err error
1828 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1829 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1830 return false, err
1831 }
1832 if onuGemInfo != nil {
1833 for _, uni := range onuGemInfo.UniPorts {
1834 uniID := plt.UniIDFromPortNum(uni)
1835 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1836 if len(tpIDs) != 0 {
1837 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1838 tpInstExists = true
1839 break
1840 }
1841 }
1842 }
1843 }
1844 return tpInstExists, nil
1845 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301846}
1847
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001848// processDiscONULOSClear clears the LOS Alarm if it's needed
1849func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301850 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001851 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301852
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001853 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1854 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1855 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1856 OnuLosRaise event sent for it */
1857 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1858 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1859 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1860 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1861 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1862 "currentIntfId": onuDiscInd.GetIntfId()})
1863 // TODO:: Should we need to ignore raising OnuLosClear event
1864 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301865 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001866 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1867 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1868 alarmInd.LosStatus = statusCheckOff
1869 go func() {
1870 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1871 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1872 }
1873 }()
1874 // stop iterating
1875 return false
1876 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301877 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001878 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301879}
1880
bseeniva43b5a912025-06-05 12:48:15 +05301881func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1882 if err != nil || tpInstExists {
1883 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1884 } else {
1885 // once the function completes set the value to false so that
1886 // we know the processing has inProcess.
1887 // Note that this is done after checking if we are already processing
1888 // to avoid changing the value from a different thread
1889 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1890 dh.discOnus.Store(sn, false)
1891 }
1892}
1893
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301894func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301895 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301896 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301897
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301898 channelID := onuDiscInd.GetIntfId()
1899 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1900
1901 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301902 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301903 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301904 }()
1905
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301906 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1907
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301908 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1909 if !dh.cfg.ForceOnuDiscIndProcessing {
1910 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1911 if error != nil {
1912 return error
1913 }
1914 if tpInstExists {
1915 // ignore the discovery if tpinstance is present.
1916 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1917 return nil
1918 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001919 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001920 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1921
1922 // if the ONU existed, handle the LOS Alarm
1923 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001924 if inProcess.(bool) {
1925 // if we're currently processing the ONU on a different thread, do nothing
1926 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1927 return nil
1928 }
1929 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1930 // then continue processing it
1931 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1932
1933 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001934 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301935 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001936 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001937
1938 // check the ONU is already know to the OLT
1939 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301940 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001941 ParentId: dh.device.Id,
1942 SerialNumber: sn,
1943 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001944
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301945 if error != nil {
1946 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1947 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001948 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 -08001949 switch e.Code() {
1950 case codes.Internal:
1951 // this probably means NOT FOUND, so just create a new device
1952 onuDevice = nil
1953 case codes.DeadlineExceeded:
1954 // if the call times out, cleanup and exit
1955 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301956 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1957 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001958 }
1959 }
1960 }
1961
1962 if onuDevice == nil {
1963 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001964 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001965 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001966 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301967 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001968 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001969
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301970 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001971 // if we can't create an ID in resource manager,
1972 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001973 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301974
1975 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001976 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301977 "serial-number": sn}, error)
1978 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001979 }
1980
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301981 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001982 ParentId: dh.device.Id,
1983 ParentPortNo: parentPortNo,
1984 ChannelId: channelID,
1985 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1986 SerialNumber: sn,
1987 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301988 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001989 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001990 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301991
1992 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001993 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301994 "serial-number": sn}, error)
1995 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001996 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301997 if error = dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301998 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1999 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2000 "onu-id": onuID,
2001 "device-id": dh.device.Id,
2002 "serial-number": sn}, error)
2003 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002004 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002005 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302006 log.Fields{"onuDevice": onuDevice,
2007 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002008 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302009 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002010 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002011
khenaidoo106c61a2021-08-11 18:05:46 -04002012 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2013 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302014 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002015 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302016 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302017 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2018 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002019 }
2020
Matteo Scandolo945e4012019-12-12 14:16:11 -08002021 // we can now use the existing ONU Id
2022 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302023 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002024 //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 +00002025 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002026 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302027 "intfId": onuDiscInd.GetIntfId(),
2028 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002029 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002030
khenaidoo106c61a2021-08-11 18:05:46 -04002031 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302032 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002033 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302034 log.Fields{"onu": onuDev,
2035 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002036
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302037 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002038 DeviceId: onuDevice.Id,
2039 ParentDeviceId: dh.device.Id,
2040 OperStatus: common.OperStatus_DISCOVERED,
2041 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302042 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302043 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002044 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302045 "serial-number": sn}, error)
2046 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002047 }
khenaidoo106c61a2021-08-11 18:05:46 -04002048
Neha Sharma96b7bf22020-06-15 10:37:32 +00002049 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302050 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302051 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002052 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302053 "serial-number": sn}, error)
2054 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002055 }
2056 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002057}
2058
Mahir Gunyelb0046752021-02-26 13:51:05 -08002059func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002060 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002061 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002062 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002063 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002064 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302065 log.Fields{"onuId": onuInd.OnuId,
2066 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302067 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002068 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002069 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002070 errFields := log.Fields{"device-id": dh.device.Id}
2071
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302072 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302073 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002074 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002075 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002076 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002077 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302078 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002079 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002080 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002081 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002082 errFields["onu-id"] = onuInd.OnuId
2083 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002084 }
khenaidoodc2116e2021-10-19 17:33:19 -04002085 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002086 ParentId: dh.device.Id,
2087 SerialNumber: serialNumber,
2088 OnuId: onuInd.OnuId,
2089 ParentPortNo: ponPort,
2090 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002091 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002092
David K. Bainbridge794735f2020-02-11 21:01:37 -08002093 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002094 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002095 }
2096
David K. Bainbridge794735f2020-02-11 21:01:37 -08002097 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002098 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002099 "previousIntfId": onuDevice.ParentPortNo,
2100 "currentIntfId": ponPort})
2101 }
2102
2103 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002104 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302105 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2106 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302107 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002108 }
2109 if !foundInCache {
2110 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002111 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 -08002112 }
kesavand7cf3a052020-08-28 12:49:18 +05302113 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002114 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002115 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302116 }
2117 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002118 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002119 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002120 }
2121 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002122}
2123
Neha Sharma96b7bf22020-06-15 10:37:32 +00002124func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 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 -07002126 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2127 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2128 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2129 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002130 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002131 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2132 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002133 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002134 onuInd.OperState = "down"
2135 }
2136 }
2137
David K. Bainbridge794735f2020-02-11 21:01:37 -08002138 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002139 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002140 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 -04002141
khenaidoodc2116e2021-10-19 17:33:19 -04002142 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002143 DeviceId: onuDevice.Id,
2144 OnuIndication: onuInd,
2145 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002146 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302147 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002148 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002149 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002150 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002151 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002152 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002153 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002154 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002155 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002156 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002157}
2158
cuilin20187b2a8c32019-03-26 19:52:28 -07002159func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2160 if serialNum != nil {
2161 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002162 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002163 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002164}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002165func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2166 decodedStr, err := hex.DecodeString(serialNum[4:])
2167 if err != nil {
2168 return nil, err
2169 }
2170 return &oop.SerialNumber{
2171 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002172 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002173 }, nil
2174}
cuilin20187b2a8c32019-03-26 19:52:28 -07002175
2176func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002177 if len(vendorSpecific) > 3 {
2178 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2179 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2180 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2181 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2182 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2183 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2184 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2185 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2186 return tmp
2187 }
2188 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002189}
2190
Mahir Gunyela2e68702022-12-07 00:00:42 -08002191// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002192func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302193 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002194}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002195
Mahir Gunyela2e68702022-12-07 00:00:42 -08002196// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2198 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302199 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002200 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302201 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002202
khenaidoodc2116e2021-10-19 17:33:19 -04002203 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002204 ParentId: dh.device.Id,
2205 OnuId: onuID,
2206 ParentPortNo: parentPort,
2207 })
2208
Girish Gowdru0c588b22019-04-23 23:24:56 -04002209 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002210 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002211 "intf-id": parentPort,
2212 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002213 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002214 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 -08002215 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302216}
2217
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002218// SendPacketInToCore sends packet-in to core
2219// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2220// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002222 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002223 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002224 "port": logicalPort,
2225 "packet": hex.EncodeToString(packetPayload),
2226 "device-id": dh.device.Id,
2227 })
2228 }
khenaidoo106c61a2021-08-11 18:05:46 -04002229
khenaidoodc2116e2021-10-19 17:33:19 -04002230 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002231 DeviceId: dh.device.Id,
2232 Port: logicalPort,
2233 Packet: packetPayload,
2234 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302235 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002236 "source": "adapter",
2237 "destination": "core",
2238 "device-id": dh.device.Id,
2239 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002240 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002241 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002242 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002244 "packet": hex.EncodeToString(packetPayload),
2245 "device-id": dh.device.Id,
2246 })
2247 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002248 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002249}
2250
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002251// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002252func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002254
2255 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2256 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002257 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002258 }
2259
Kent Hagermane6ff1012020-07-14 15:07:53 -04002260 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002261 metrics := dh.metrics.GetSubscriberMetrics()
2262 for _, m := range pmConfigs.Metrics {
2263 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002264 }
2265 }
2266}
2267
khenaidoodc2116e2021-10-19 17:33:19 -04002268func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002269 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002270 var errorsList []error
2271
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002272 if dh.getDeviceDeletionInProgressFlag() {
2273 // The device itself is going to be reset as part of deletion. So nothing to be done.
2274 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2275 return nil
2276 }
2277
Girish Gowdru0c588b22019-04-23 23:24:56 -04002278 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002279 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302280 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002281
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302283 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002284 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302285 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002286 if flow_utils.HasGroup(flow) {
2287 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2288 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002289 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2290 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2291 } else {
2292 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2293 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002294 }
Girish Gowdracefae192020-03-19 18:14:10 -07002295 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002296 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302297 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002298 logger.Warnw(ctx, "flow-to-remove-not-found",
2299 log.Fields{
2300 "ponIf": intfID,
2301 "flowToRemove": flow,
2302 "error": err,
2303 })
2304 } else {
2305 errorsList = append(errorsList, err)
2306 }
Girish Gowdracefae192020-03-19 18:14:10 -07002307 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002308 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302309
2310 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302311 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302313 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002314 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302315 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002316 if flow_utils.HasGroup(flow) {
2317 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2318 } else {
yasin saplid0566272021-12-21 09:10:30 +00002319 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002320 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2321 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2322 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2323 } else {
yasin saplid0566272021-12-21 09:10:30 +00002324 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002325 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002326 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002327 if err != nil {
2328 errorsList = append(errorsList, err)
2329 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302330 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002331 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002332
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002333 return errorsList
2334}
2335
2336func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2337 var err error
2338 var errorsList []error
2339
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002340 if dh.getDeviceDeletionInProgressFlag() {
2341 // The device itself is going to be reset as part of deletion. So nothing to be done.
2342 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2343 return nil
2344 }
2345
Girish Gowdracefae192020-03-19 18:14:10 -07002346 // 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 +00002347 if groups != nil {
2348 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002349 // err = dh.groupMgr.AddGroup(ctx, group)
2350 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002351 if err != nil {
2352 errorsList = append(errorsList, err)
2353 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002354 }
2355 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002356 // err = dh.groupMgr.ModifyGroup(ctx, group)
2357 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002358 if err != nil {
2359 errorsList = append(errorsList, err)
2360 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002362 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002363 // err = dh.groupMgr.DeleteGroup(ctx, group)
2364 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002365 if err != nil {
2366 errorsList = append(errorsList, err)
2367 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002368 }
2369 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002370
2371 return errorsList
2372}
2373
Mahir Gunyela2e68702022-12-07 00:00:42 -08002374// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002375func (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 -07002376 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002377
2378 if dh.getDeviceDeletionInProgressFlag() {
2379 // The device itself is going to be reset as part of deletion. So nothing to be done.
2380 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2381 return nil
2382 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302383 if dh.transitionMap.currentDeviceState != deviceStateUp {
2384 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2385 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2386 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002387 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2388 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2389 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002390 if len(errorsList) > 0 {
2391 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2392 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002394 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302395}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002396
Mahir Gunyela2e68702022-12-07 00:00:42 -08002397// DisableDevice disables the given device
2398// It marks the following for the given device:
2399// Device-Handler Admin-State : down
2400// Device Port-State: UNKNOWN
2401// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002403 /* On device disable ,admin state update has to be done prior sending request to agent since
2404 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002405 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002406 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002407 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002408 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002409 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002410 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002411 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002412 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002413 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002414 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302415
2416 dh.discOnus = sync.Map{}
2417 dh.onus = sync.Map{}
2418
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002419 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302420 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002421 if dh.isCollectorActive {
2422 dh.stopCollector <- true
2423 }
2424 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302425
Neha Sharma96b7bf22020-06-15 10:37:32 +00002426 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002427 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302428 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302429 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002430
kdarapu1afeceb2020-02-12 01:38:09 -05002431 // 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 -04002432 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002433 DeviceId: cloned.Id,
2434 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2435 OperStatus: voltha.OperStatus_UNKNOWN,
2436 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002437 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002438 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002439 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002440 return nil
2441}
2442
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002444 // Update onu state as unreachable in onu adapter
2445 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302446 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002447
Akash Kankanala041a2122024-10-16 15:49:22 +05302448 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002449 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002450 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002451 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 -04002452 }
2453 if onuDevices != nil {
2454 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002455 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002456 DeviceId: onuDevice.Id,
2457 OnuIndication: &onuInd,
2458 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002459 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002460 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002461 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002462 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002463 }
2464 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002465}
2466
Mahir Gunyela2e68702022-12-07 00:00:42 -08002467// ReenableDevice re-enables the olt device after disable
2468// It marks the following for the given device:
2469// Device-Handler Admin-State : up
2470// Device Port-State: ACTIVE
2471// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302473 if dh.Client != nil {
2474 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2475 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2476 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2477 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302478 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302479 } else {
2480 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302481 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002482 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002483
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002484 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002485 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002486 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002487 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002488 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2489 } else {
2490 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2491 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2492 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002493 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002494 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302495 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002496 device.OperStatus = voltha.OperStatus_ACTIVE
2497 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302498 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002499 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002500 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002501 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002502
khenaidoodc2116e2021-10-19 17:33:19 -04002503 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002504 DeviceId: device.Id,
2505 OperStatus: device.OperStatus,
2506 ConnStatus: device.ConnectStatus,
2507 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302508 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002509 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002510 "connect-status": device.ConnectStatus,
2511 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002512 }
kesavand39e0aa32020-01-28 20:58:50 -05002513
Neha Sharma96b7bf22020-06-15 10:37:32 +00002514 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002515
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002516 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002517}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002518
npujarec5762e2020-01-01 14:08:48 +05302519func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002520 var uniID uint32
2521 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002522 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302523 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002524 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002525 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002526 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002527 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2528 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2529 } else {
2530 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2531 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002532 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002533 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002534 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002535 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002536 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002537 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002538 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002539 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002540 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002541 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002542 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002543 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002544 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002545 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002546 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002547 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302548 }
yasin saplibddc2d72022-02-08 13:10:17 +00002549 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2550 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002551 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002552 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302553 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002554 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002555 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002556 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 -03002557 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002558 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002559 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002560 if len(errs) > 0 {
2561 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2562 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2563 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002564 return nil
2565}
2566
Devmalya Paul495b94a2019-08-27 19:42:00 -04002567// 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 +05302568func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002569 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002570 /* Clear the KV store data associated with the all the UNI ports
2571 This clears up flow data and also resource map data for various
2572 other pon resources like alloc_id and gemport_id
2573 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002574
2575 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002576 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002577
Himani Chawla49a5d562020-11-25 11:53:44 +05302578 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002579 // Stop the Stats collector
2580 if dh.isCollectorActive {
2581 dh.stopCollector <- true
2582 }
2583 // stop the heartbeat check routine
2584 if dh.isHeartbeatCheckActive {
2585 dh.stopHeartbeatCheck <- true
2586 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302587 // Stop the read indication only if it the routine is active
2588 if dh.isReadIndicationRoutineActive {
2589 dh.stopIndications <- true
2590 }
2591 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302592
2593 err := dh.cleanupDeviceResources(ctx)
2594 if err != nil {
2595 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2596 } else {
2597 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2598 }
2599
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002600 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302601 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002602 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302603 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002604 go func() {
2605 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302606 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2607 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002608 }
2609 }()
2610 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002611 }
2612 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002613 // There is no need to update the core about operation status and connection status of the OLT.
2614 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2615 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2616 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002617
khenaidoo7eb2d672021-10-22 19:08:50 -04002618 // Stop the adapter grpc clients for that parent device
2619 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002620 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002621}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002622
2623// StopAllFlowRoutines stops all flow routines
2624func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2625 var wg sync.WaitGroup
2626 wg.Add(1) // for the mcast routine below to finish
2627 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2628 for _, flMgr := range dh.flowMgr {
2629 if flMgr != nil {
2630 wg.Add(1) // for the flow handler routine below to finish
2631 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2632 }
2633 }
2634 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2635 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2636 } else {
2637 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2638 }
2639}
2640
Gustavo Silva41af9122022-10-11 11:05:13 -03002641func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2642 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002643 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302644 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002645 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002646 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002647 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002648 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002649 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2650 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302651 }
2652 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002653 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2654 errs = append(errs, err)
2655 }
2656 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2657 errs = append(errs, err)
2658 }
2659 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2660 errs = append(errs, err)
2661 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002662 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002663 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002664 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002665 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002666 }
2667 // Clean up NNI manager's data
2668 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2669 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002670 }
A R Karthick1f85b802019-10-11 05:06:05 +00002671
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002672 dh.CloseKVClient(ctx)
2673
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002674 // Take one final sweep at cleaning up KV store for the OLT device
2675 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002676 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2677 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002678 }
2679
Devmalya Paul495b94a2019-08-27 19:42:00 -04002680 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302681 dh.onus.Range(func(key interface{}, value interface{}) bool {
2682 dh.onus.Delete(key)
2683 return true
2684 })
2685
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002686 /*Delete discovered ONU map for the device*/
2687 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2688 dh.discOnus.Delete(key)
2689 return true
2690 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002691 if len(errs) > 0 {
2692 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2693 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2694 }
2695 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002696}
2697
Mahir Gunyela2e68702022-12-07 00:00:42 -08002698// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002699func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302700 if dh.Client != nil {
2701 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2702 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2703 }
2704 } else {
2705 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002706 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302707
Neha Sharma96b7bf22020-06-15 10:37:32 +00002708 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002709 return nil
2710}
2711
David K. Bainbridge794735f2020-02-11 21:01:37 -08002712func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002713 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002714 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002715 "packet-indication": *packetIn,
2716 "device-id": dh.device.Id,
2717 "packet": hex.EncodeToString(packetIn.Pkt),
2718 })
2719 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002720 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2721 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2722 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002723 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002724 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002725 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002726 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002727 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002728 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002729 "logical-port-num": logicalPortNum,
2730 "device-id": dh.device.Id,
2731 "packet": hex.EncodeToString(packetIn.Pkt),
2732 })
2733 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002734
khenaidoodc2116e2021-10-19 17:33:19 -04002735 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002736 DeviceId: dh.device.Id,
2737 Port: logicalPortNum,
2738 Packet: packetIn.Pkt,
2739 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302740 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002741 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302742 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002743 "device-id": dh.device.Id,
2744 "packet": hex.EncodeToString(packetIn.Pkt),
2745 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002746 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002747
Matteo Scandolo92186242020-06-12 10:54:18 -07002748 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002749 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002750 "packet": hex.EncodeToString(packetIn.Pkt),
2751 "device-id": dh.device.Id,
2752 })
2753 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002754 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002755}
2756
Mahir Gunyela2e68702022-12-07 00:00:42 -08002757// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2758func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2759 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2760 if err != nil {
2761 return olterrors.NewErrInvalidValue(log.Fields{
2762 "egress-nni-port": egressPortNo,
2763 "device-id": dh.device.Id,
2764 }, err)
2765 }
2766 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2767
2768 if logger.V(log.DebugLevel) {
2769 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2770 "uplink-pkt": uplinkPkt,
2771 "packet": hex.EncodeToString(packet.Data),
2772 "device-id": dh.device.Id,
2773 })
2774 }
2775
2776 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2777 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2778 "packet": hex.EncodeToString(packet.Data),
2779 "device-id": dh.device.Id,
2780 }, err)
2781 }
2782 return nil
2783}
2784
2785// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2786func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2787 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2788 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2789 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2790 // Do not packet-out lldp packets on uni port.
2791 // ONOS has no clue about uni/nni ports, it just packets out on all
2792 // available ports on the Logical Switch. It should not be interested
2793 // in the UNI links.
2794 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2795 "device-id": dh.device.Id,
2796 })
2797 return nil
2798 }
2799 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2800 if innerEthType == 0x8100 {
2801 // q-in-q 802.1ad or 802.1q double tagged packet.
2802 // slice out the outer tag.
2803 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2804 if logger.V(log.DebugLevel) {
2805 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2806 "packet-data": hex.EncodeToString(packet.Data),
2807 "device-id": dh.device.Id,
2808 })
2809 }
2810 }
2811 }
2812 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2813 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2814 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2815 var gemPortID uint32
2816 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2817 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2818 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2819 }
2820 if err != nil {
2821 // In this case the openolt agent will receive the gemPortID as 0.
2822 // The agent tries to retrieve the gemPortID in this case.
2823 // This may not always succeed at the agent and packetOut may fail.
2824 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2825 "intf-id": intfID,
2826 "onu-id": onuID,
2827 "uni-id": uniID,
2828 "packet": hex.EncodeToString(packet.Data),
2829 "device-id": dh.device.Id,
2830 "error": err,
2831 })
2832 }
2833
2834 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2835 if logger.V(log.DebugLevel) {
2836 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2837 "egress-port-no": egressPortNo,
2838 "intf-id": intfID,
2839 "onu-id": onuID,
2840 "uni-id": uniID,
2841 "gem-port-id": gemPortID,
2842 "packet": hex.EncodeToString(packet.Data),
2843 "device-id": dh.device.Id,
2844 })
2845 }
2846
2847 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2848 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2849 "source": "adapter",
2850 "destination": "onu",
2851 "egress-port-number": egressPortNo,
2852 "intf-id": intfID,
2853 "oni-id": onuID,
2854 "uni-id": uniID,
2855 "gem-port-id": gemPortID,
2856 "packet": hex.EncodeToString(packet.Data),
2857 "device-id": dh.device.Id,
2858 }, err)
2859 }
2860 return nil
2861}
2862
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002863// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002864func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002865 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002866 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002867 "device-id": dh.device.Id,
2868 "egress-port-no": egressPortNo,
2869 "pkt-length": len(packet.Data),
2870 "packet": hex.EncodeToString(packet.Data),
2871 })
2872 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002873
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002874 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002875 var err error
mgouda86543582025-10-29 20:58:16 +05302876 switch egressPortType {
2877 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002878 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302879 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002880 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302881 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002882 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302883 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002884 "egressPortType": egressPortType,
2885 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302886 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002887 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002888 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002889 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002890}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002891
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002892func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2893 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002894}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302895
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002896func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002897 defer func() {
2898 dh.lockDevice.Lock()
2899 dh.isHeartbeatCheckActive = false
2900 dh.lockDevice.Unlock()
2901 }()
2902
2903 dh.lockDevice.Lock()
2904 dh.isHeartbeatCheckActive = true
2905 dh.lockDevice.Unlock()
2906
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302907 // start the heartbeat check towards the OLT.
2908 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302909 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302910
2911 for {
2912 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2913 select {
2914 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002915 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002916 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002917 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302918 if timerCheck == nil {
2919 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002920 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302921 }
2922 } else {
2923 if timerCheck != nil {
2924 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002925 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302926 }
2927 timerCheck = nil
2928 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302929 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2930 if dh.heartbeatSignature == 0 {
2931 // First time the signature will be 0, update the signture to DB when not found.
2932 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2933 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2934 }
2935 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2936
2937 dh.lockDevice.RLock()
2938 // Stop the read indication only if it the routine is active
2939 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2940 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2941 // on next execution of the readIndication routine.
2942 if !dh.isReadIndicationRoutineActive {
2943 // Start reading indications
2944 go func() {
2945 if err = dh.readIndications(ctx); err != nil {
2946 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2947 }
2948 }()
2949 }
2950 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302951 } else {
2952 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2953 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2954 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2955 go dh.updateStateRebooted(ctx)
2956 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302957 }
2958 cancel()
2959 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002960 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302961 return
2962 }
2963 }
2964}
2965
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002966func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002967 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002968 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002969 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2970 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2971 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2972 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2973 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002974 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002975 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2976 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002977 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302978
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302979 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002980 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002981 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002982 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002983 DeviceId: dh.device.Id,
2984 OperStatus: voltha.OperStatus_UNKNOWN,
2985 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2986 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002987 _ = 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 -04002988 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302989 /*
2990 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2991 DeviceId: dh.device.Id,
2992 PortTypeFilter: 0,
2993 OperStatus: voltha.OperStatus_UNKNOWN,
2994 }); err != nil {
2995 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2996 }
2997 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002998
Akash Kankanala041a2122024-10-16 15:49:22 +05302999 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003000 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003001 cloned := proto.Clone(device).(*voltha.Device)
3002 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3003 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3004 dh.device = cloned // update local copy of the device
3005 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003006
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003007 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003008 // Stop the Stats collector
3009 if dh.isCollectorActive {
3010 dh.stopCollector <- true
3011 }
3012 // stop the heartbeat check routine
3013 if dh.isHeartbeatCheckActive {
3014 dh.stopHeartbeatCheck <- true
3015 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003016 // Stop the read indication only if it the routine is active
3017 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3018 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3019 // on next execution of the readIndication routine.
3020 if dh.isReadIndicationRoutineActive {
3021 dh.stopIndications <- true
3022 }
3023 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003024 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303025 }
3026}
kesavand39e0aa32020-01-28 20:58:50 -05003027
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303028func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3029 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3030 if err != nil || device == nil {
3031 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3032 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3033 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3034 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3035 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3036 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3037 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3038 return
3039 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303040 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003041 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303042
3043 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3044 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303045 // First, stop the read indication and heartbeat check routines to prevent any delay
3046 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303047 dh.lockDevice.RLock()
3048 // Stop the read indication only if it the routine is active
3049 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3050 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3051 // on next execution of the readIndication routine.
3052 if dh.isReadIndicationRoutineActive {
3053 dh.stopIndications <- true
3054 }
3055 dh.lockDevice.RUnlock()
3056
bseenivad1c984b2025-01-09 12:54:44 +05303057 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3058 DeviceId: dh.device.Id,
3059 OperStatus: voltha.OperStatus_REBOOTED,
3060 ConnStatus: voltha.ConnectStatus_REACHABLE,
3061 }); err != nil {
3062 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3063 }
3064
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303065 //raise olt communication failure event
3066 raisedTs := time.Now().Unix()
3067 cloned := proto.Clone(device).(*voltha.Device)
3068 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3069 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3070 dh.device = cloned // update local copy of the device
3071 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3072
Gustavo Silva41af9122022-10-11 11:05:13 -03003073 if err := dh.cleanupDeviceResources(ctx); err != nil {
3074 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3075 } else {
3076 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3077 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003078
3079 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303080 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003081 if dh.isCollectorActive {
3082 dh.stopCollector <- true
3083 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303084 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003085 if dh.isHeartbeatCheckActive {
3086 dh.stopHeartbeatCheck <- true
3087 }
3088 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303089
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003090 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303091
Akash Kankanala041a2122024-10-16 15:49:22 +05303092 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303093 dh.adapterPreviouslyConnected = false
3094 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303095 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3096 if err != nil || childDevices == nil {
3097 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3098 continue
3099 }
3100 if len(childDevices.Items) == 0 {
3101 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3102 break
3103 } else {
3104 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3105 time.Sleep(5 * time.Second)
3106 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303107 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303108 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003109 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303110 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3111 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303112}
3113
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303114// EnableOnuSerialNumber to enable onu serial number
3115func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3116 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3117 onuSerialNumber := device.SerialNumber
3118
3119 // fetch interfaceid from PortNo
3120 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3121
3122 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3123 if err != nil {
3124 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3125 log.Fields{
3126 "devicer-id": dh.device.Id,
3127 "serial-number": onuSerialNumber}, err).Log()
3128 }
3129
3130 onuIntf := &oop.InterfaceOnuSerialNumber{
3131 IntfId: ponID,
3132 OnuSerialNumber: sn,
3133 }
3134 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3135
3136 if err != nil {
3137 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3138 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3139 "device-id": dh.device.Id,
3140 "onu-serial-number": onuSerialNumber}, err)
3141 }
3142 return nil
3143}
3144
3145// DisableOnuSerialNumber to disable onu serial number
3146func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3147 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3148 onuSerialNumber := device.SerialNumber
3149 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3150 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3151 if err != nil {
3152 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3153 log.Fields{
3154 "devicer-id": dh.device.Id,
3155 "serial-number": onuSerialNumber}, err).Log()
3156 }
3157
3158 onuIntf := &oop.InterfaceOnuSerialNumber{
3159 OnuSerialNumber: sn,
3160 IntfId: ponID,
3161 }
3162 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3163
3164 if err != nil {
3165 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3166 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3167 "device-id": dh.device.Id,
3168 "onu-serial-number": onuSerialNumber}, err)
3169 }
3170 return nil
3171}
3172
3173// EnableOnu to enable onu
3174func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3175 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3176 onuSerialNumber := device.SerialNumber
3177 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3178 if InCacheOnuDev == nil {
3179 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3180 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3181 "device-id": dh.device.Id,
3182 "onu-serial-number": onuSerialNumber}, nil)
3183 }
3184 logger.Debugw(ctx, "successfully-received-child-device-from-cache", log.Fields{"child-device-intfid": InCacheOnuDev.intfID, "child-device-sn": InCacheOnuDev.serialNumber, "child-onuid": InCacheOnuDev.onuID})
3185
3186 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3187 if err != nil {
3188 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3189 log.Fields{
3190 "device-id": dh.device.Id,
3191 "serial-number": onuSerialNumber}, err).Log()
3192 }
3193
3194 onuIntf := &oop.InterfaceOnuSerialNumber{
3195 OnuSerialNumber: sn,
3196 IntfId: InCacheOnuDev.intfID,
3197 }
3198 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3199 OnuId: InCacheOnuDev.onuID,
3200 IntfIdSerialNum: onuIntf,
3201 }
3202 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3203
3204 if err != nil {
3205 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3206 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3207 "olt-device-id": dh.device.Id,
3208 "onu-serial-number": onuSerialNumber}, err)
3209 }
3210 return nil
3211}
3212
3213// DisableOnu to disable onu
3214func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3215 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3216 onuSerialNumber := device.SerialNumber
3217 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3218 if InCacheOnuDev == nil {
3219 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3220 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3221 "device-id": dh.device.Id,
3222 "onu-serial-number": onuSerialNumber}, nil)
3223 }
3224 logger.Debugw(ctx, "successfully-received-child-device-from-cache", log.Fields{"child-device-intfid": InCacheOnuDev.intfID, "child-device-sn": InCacheOnuDev.serialNumber, "child-onuid": InCacheOnuDev.onuID})
3225
3226 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3227 if err != nil {
3228 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3229 log.Fields{
3230 "device-id": dh.device.Id,
3231 "serial-number": onuSerialNumber}, err).Log()
3232 }
3233
3234 onuIntf := &oop.InterfaceOnuSerialNumber{
3235 OnuSerialNumber: sn,
3236 IntfId: InCacheOnuDev.intfID,
3237 }
3238 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3239 OnuId: InCacheOnuDev.onuID,
3240 IntfIdSerialNum: onuIntf,
3241 }
3242 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3243
3244 if err != nil {
3245 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3246 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3247 "olt-device-id": dh.device.Id,
3248 "onu-serial-number": onuSerialNumber}, err)
3249 }
3250 return nil
3251}
3252
kesavand39e0aa32020-01-28 20:58:50 -05003253// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003254func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3255 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3256 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003257}
3258
3259// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003260func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3261 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3262 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003263}
3264
Mahir Gunyela2e68702022-12-07 00:00:42 -08003265// 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 +00003266func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3267 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003268 if port.GetType() == voltha.Port_ETHERNET_NNI {
3269 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003270 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303271 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303272 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003273 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003274 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003275 }
3276 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003277 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003278 ponIntf := &oop.Interface{IntfId: ponID}
3279 var operStatus voltha.OperStatus_Types
3280 if enablePort {
3281 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303282 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003283
3284 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303285 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003286 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003287 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003288 }
3289 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003290 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003291 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003292 } else {
3293 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303294 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003295 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303296 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003297 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003298 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003299 }
3300 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003301 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003302 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003303 }
khenaidoodc2116e2021-10-19 17:33:19 -04003304 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003305 DeviceId: dh.device.Id,
3306 PortType: voltha.Port_PON_OLT,
3307 PortNo: port.PortNo,
3308 OperStatus: operStatus,
3309 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303310 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303311 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003312 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003313 }
3314 return nil
3315}
3316
Mahir Gunyela2e68702022-12-07 00:00:42 -08003317// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003318func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003319 // Disable the port and update the oper_port_status to core
3320 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003321 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003322 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003323 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303324 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303325 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003326 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003327 }
3328 }
3329 }
3330 return nil
3331}
3332
Mahir Gunyela2e68702022-12-07 00:00:42 -08003333// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003334func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3335 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3336 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003337 if port.Type == voltha.Port_ETHERNET_NNI {
3338 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003339 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003340 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003341 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003342 }
3343 }
3344 if port.Type == voltha.Port_PON_OLT {
3345 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003346 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003347 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003348 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003349 }
3350 }
3351 }
3352}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003353
3354// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003355func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003356 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003357 if dh.getDeviceDeletionInProgressFlag() {
3358 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3359 // will reboot, so everything will be reset on the pOLT too.
3360 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3361 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3362 return nil
3363 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303364
3365 if dh.transitionMap.currentDeviceState != deviceStateUp {
3366 logger.Warnw(ctx, "device-is-not-up--not-handling-child-device-lost", log.Fields{"device-id": dh.device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
3367 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3368 }
3369
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003370 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003371 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003372
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003373 var sn *oop.SerialNumber
3374 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003375 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303376 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003377 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303378 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003379 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003380 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003381
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003382 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303383 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003384 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003385 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3386 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3387 "device-id": dh.device.Id,
3388 "intf-id": intfID,
3389 "onuID": onuID,
3390 "err": err})
3391 } else {
3392 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003393 // Delete flows from device before schedulers and queue
3394 // Clear flowids for gem cache.
3395 removedFlows := []uint64{}
3396 for _, gem := range onuGem.GemPorts {
3397 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3398 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303399 // multiple gem port can have the same flow id
3400 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003401 var alreadyRemoved bool
3402 for _, removedFlowID := range removedFlows {
3403 if removedFlowID == flowID {
3404 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3405 alreadyRemoved = true
3406 break
3407 }
3408 }
3409 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003410 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003411 removedFlows = appendUnique64bit(removedFlows, flowID)
3412 }
3413 }
3414 }
3415 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3416 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003417 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3418 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3419 "device-id": dh.device.Id,
3420 "onu-device": onu,
3421 "err": err})
3422 }
yasin saplibddc2d72022-02-08 13:10:17 +00003423 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003424 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3425 "intf-id": intfID,
3426 "onu-device": onu,
3427 "onu-gem": onuGem,
3428 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303429 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003430 }
3431 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003432 }
yasin saplibddc2d72022-02-08 13:10:17 +00003433 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003434 dh.onus.Delete(onuKey)
3435 dh.discOnus.Delete(onuSn)
3436
3437 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003438 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303439 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303440 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003441 "onu-id": onuID}, err).Log()
3442 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003443
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003444 return nil
3445}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003446func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3447 flow := &oop.Flow{FlowId: flowID}
3448 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3449 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3450 "device-id": dh.device.Id})
3451 } else {
3452 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3453 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3454 "device-id": dh.device.Id,
3455 "err": err})
3456 }
3457 }
3458}
Girish Gowdracefae192020-03-19 18:14:10 -07003459
3460func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003461 for _, field := range flow_utils.GetOfbFields(flow) {
3462 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003463 return field.GetPort()
3464 }
3465 }
3466 return InvalidPort
3467}
3468
3469func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003470 for _, action := range flow_utils.GetActions(flow) {
3471 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003472 if out := action.GetOutput(); out != nil {
3473 return out.GetPort()
3474 }
3475 }
3476 }
3477 return InvalidPort
3478}
3479
Girish Gowdracefae192020-03-19 18:14:10 -07003480func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3481 inPort := getInPortFromFlow(flow)
3482 outPort := getOutPortFromFlow(flow)
3483
3484 if inPort == InvalidPort || outPort == InvalidPort {
3485 return inPort, outPort
3486 }
3487
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003488 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003489 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003490 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003491 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003492 return uniPort, outPort
3493 }
3494 }
3495 } else {
3496 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003497 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003498 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003499 return inPort, uniPort
3500 }
3501 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003502 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003503 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003504 return uniPort, outPort
3505 }
3506 }
3507 }
3508
3509 return InvalidPort, InvalidPort
3510}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003511
3512func extractOmciTransactionID(omciPkt []byte) uint16 {
3513 if len(omciPkt) > 3 {
3514 d := omciPkt[0:2]
3515 transid := binary.BigEndian.Uint16(d)
3516 return transid
3517 }
3518 return 0
3519}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003520
3521// StoreOnuDevice stores the onu parameters to the local cache.
3522func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3523 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3524 dh.onus.Store(onuKey, onuDevice)
3525}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003526
khenaidoodc2116e2021-10-19 17:33:19 -04003527func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003528 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003529 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003530 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003531 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003532 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003533 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003534 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003535 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3536 return nil, err
3537 }
3538 ID = device.ProxyAddress.GetOnuId()
3539 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3540 valueparam.Onu = &Onu
3541 valueparam.Value = value
3542
3543 // This API is unsupported until agent patch is added
3544 resp.Unsupported = uint32(value)
3545 _ = ctx
3546
3547 // Uncomment this code once agent changes are complete and tests
3548 /*
3549 resp, err = dh.Client.GetValue(ctx, valueparam)
3550 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003551 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003552 return nil, err
3553 }
3554 */
3555
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003556 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 -08003557 return resp, nil
3558}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003559
Akash Kankanala041a2122024-10-16 15:49:22 +05303560func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003561 // Default to NNI
3562 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003563 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003564 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003565 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003566 }
3567 return intfID
3568}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003569
Akash Kankanala041a2122024-10-16 15:49:22 +05303570func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003571 dh.perPonOnuIndicationChannelLock.Lock()
3572 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3573 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003574 return ch.indicationChannel
3575 }
3576 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303577 // We create a buffered channel here to avoid calling function to be blocked
3578 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003579 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003580 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003581 stopChannel: make(chan struct{}),
3582 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003583 dh.perPonOnuIndicationChannel[intfID] = channels
3584 dh.perPonOnuIndicationChannelLock.Unlock()
3585 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003586 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003587}
3588
Mahir Gunyelb0046752021-02-26 13:51:05 -08003589func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3590 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3591 dh.perPonOnuIndicationChannelLock.Lock()
3592 defer dh.perPonOnuIndicationChannelLock.Unlock()
3593 for _, v := range dh.perPonOnuIndicationChannel {
3594 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003595 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003596 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003597}
3598
Mahir Gunyelb0046752021-02-26 13:51:05 -08003599func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3600 ind := onuIndicationMsg{
3601 ctx: ctx,
3602 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003603 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003604 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003605 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303606 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003607}
3608
Mahir Gunyelb0046752021-02-26 13:51:05 -08003609func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003610 for {
3611 select {
3612 // process one indication per onu, before proceeding to the next one
3613 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003614 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003615 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003616 "ind": indication})
3617 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003618 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003619 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003620 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3621 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003622 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003623 }
3624 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003625 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003626 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3627 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003628 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003629 }
3630 }
3631 case <-onuChannels.stopChannel:
3632 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3633 close(onuChannels.indicationChannel)
3634 return
3635 }
3636 }
3637}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003638
3639// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3640// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003641func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003642 if dh.getDeviceDeletionInProgressFlag() {
3643 // The device itself is going to be reset as part of deletion. So nothing to be done.
3644 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3645 return nil
3646 }
3647
Girish Gowdra491a9c62021-01-06 16:43:07 -08003648 // Step1 : Fill McastFlowOrGroupControlBlock
3649 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3650 // Step3 : Wait on response channel for response
3651 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003652 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003653 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3654 errChan := make(chan error)
3655 var groupID uint32
3656 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3657 ctx: ctx,
3658 flowOrGroupAction: action,
3659 flow: flow,
3660 group: group,
3661 errChan: &errChan,
3662 }
3663 if flow != nil {
3664 groupID = flow_utils.GetGroup(flow)
3665 } else if group != nil {
3666 groupID = group.Desc.GroupId
3667 } else {
3668 return errors.New("flow-and-group-both-nil")
3669 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003670 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3671 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3672 // Derive the appropriate go routine to handle the request by a simple module operation.
3673 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3674 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3675 // Wait for handler to return error value
3676 err := <-errChan
3677 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3678 return err
3679 }
3680 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3681 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003682}
3683
3684// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003685func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003686 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003687 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003688 // block on the channel to receive an incoming mcast flow/group
3689 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003690 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3691 if mcastFlowOrGroupCb.flow != nil {
3692 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3693 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3694 log.Fields{"device-id": dh.device.Id,
3695 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003696 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3697 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3698 for _, flMgr := range dh.flowMgr {
3699 if flMgr != nil {
3700 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3701 break
3702 }
3703 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003704 // Pass the return value over the return channel
3705 *mcastFlowOrGroupCb.errChan <- err
3706 } else { // flow remove
3707 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3708 log.Fields{"device-id": dh.device.Id,
3709 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003710 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3711 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3712 for _, flMgr := range dh.flowMgr {
3713 if flMgr != nil {
3714 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3715 break
3716 }
3717 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003718 // Pass the return value over the return channel
3719 *mcastFlowOrGroupCb.errChan <- err
3720 }
3721 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303722 switch mcastFlowOrGroupCb.flowOrGroupAction {
3723 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003724 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3725 log.Fields{"device-id": dh.device.Id,
3726 "groupToAdd": mcastFlowOrGroupCb.group})
3727 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3728 // Pass the return value over the return channel
3729 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303730 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003731 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3732 log.Fields{"device-id": dh.device.Id,
3733 "groupToModify": mcastFlowOrGroupCb.group})
3734 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3735 // Pass the return value over the return channel
3736 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303737 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003738 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3739 log.Fields{"device-id": dh.device.Id,
3740 "groupToRemove": mcastFlowOrGroupCb.group})
3741 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3742 // Pass the return value over the return channel
3743 *mcastFlowOrGroupCb.errChan <- err
3744 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003745 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003746 case <-stopHandler:
3747 dh.mcastHandlerRoutineActive[routineIndex] = false
3748 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003749 }
3750 }
3751}
kesavand62126212021-01-12 04:56:06 -05003752
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003753// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003754func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003755 for i, v := range dh.stopMcastHandlerRoutine {
3756 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003757 select {
3758 case v <- true:
3759 case <-time.After(time.Second * 5):
3760 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3761 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003762 }
3763 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003764
3765 if dh.incomingMcastFlowOrGroup != nil {
3766 for k := range dh.incomingMcastFlowOrGroup {
3767 if dh.incomingMcastFlowOrGroup[k] != nil {
3768 dh.incomingMcastFlowOrGroup[k] = nil
3769 }
3770 }
3771 dh.incomingMcastFlowOrGroup = nil
3772 }
3773
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003774 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003775 logger.Debug(ctx, "stopped all mcast handler routines")
3776}
3777
Akash Kankanala041a2122024-10-16 15:49:22 +05303778// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003779func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003780 singleValResp := extension.SingleGetValueResponse{
3781 Response: &extension.GetValueResponse{
3782 Response: &extension.GetValueResponse_PortCoutners{
3783 PortCoutners: &extension.GetOltPortCountersResponse{},
3784 },
3785 },
3786 }
3787
Akash Kankanala041a2122024-10-16 15:49:22 +05303788 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003789 return &extension.SingleGetValueResponse{
3790 Response: &extension.GetValueResponse{
3791 Status: status,
3792 ErrReason: reason,
3793 },
3794 }
3795 }
3796
3797 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3798 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303799 // send error response
kesavand62126212021-01-12 04:56:06 -05003800 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3801 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3802 }
3803 statIndChn := make(chan bool, 1)
3804 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3805 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303806 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003807
3808 go func() {
3809 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3810 if err != nil {
3811 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3812 }
3813 }()
3814 select {
3815 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303816 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003817 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3818 case <-time.After(oltPortInfoTimeout * time.Second):
3819 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3820 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3821 case <-ctx.Done():
3822 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3823 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3824 }
mgouda86543582025-10-29 20:58:16 +05303825 switch oltPortInfo.PortType {
3826 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303827 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003828 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003829 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3830 cmnni := dh.portStats.collectNNIMetrics(intfID)
3831 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303832 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003833 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3834 }
3835 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3836 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303837 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003838 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003839 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003840 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3841 cmpon := dh.portStats.collectPONMetrics(intfID)
3842 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303843 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003844 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3845 }
3846 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3847 return &singleValResp
3848 }
3849 }
3850 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3851}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303852
Akash Kankanala041a2122024-10-16 15:49:22 +05303853//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303854func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303855 singleValResp := extension.SingleGetValueResponse{
3856 Response: &extension.GetValueResponse{
3857 Status: extension.GetValueResponse_OK,
3858 Response: &extension.GetValueResponse_OffloadedAppsStats{
3859 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3860 },
3861 },
3862 }
3863
3864 return &singleValResp
3865}
3866
Akash Kankanala041a2122024-10-16 15:49:22 +05303867//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303868func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303869 singleValResp := extension.SingleSetValueResponse{
3870 Response: &extension.SetValueResponse{
3871 Status: extension.SetValueResponse_OK,
3872 },
3873 }
3874
3875 return &singleValResp
3876}
3877
Akash Kankanala041a2122024-10-16 15:49:22 +05303878//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303879func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303880 singleValResp := extension.SingleSetValueResponse{
3881 Response: &extension.SetValueResponse{
3882 Status: extension.SetValueResponse_OK,
3883 },
3884 }
3885
3886 return &singleValResp
3887}
3888
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303889func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303890 singleValResp := extension.SingleGetValueResponse{
3891 Response: &extension.GetValueResponse{
3892 Response: &extension.GetValueResponse_OnuPonCounters{
3893 OnuPonCounters: &extension.GetOnuCountersResponse{},
3894 },
3895 },
3896 }
3897
Akash Kankanala041a2122024-10-16 15:49:22 +05303898 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303899 return &extension.SingleGetValueResponse{
3900 Response: &extension.GetValueResponse{
3901 Status: status,
3902 ErrReason: reason,
3903 },
3904 }
3905 }
3906 intfID := onuPonInfo.IntfId
3907 onuID := onuPonInfo.OnuId
3908 onuKey := dh.formOnuKey(intfID, onuID)
3909
3910 if _, ok := dh.onus.Load(onuKey); !ok {
3911 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3912 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3913 }
3914 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3915 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3916 if cmnni == nil {
3917 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3918 }
3919 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3920 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303921}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003922
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303923func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3924 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3925 if err != nil {
3926 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3927 return nil, err
3928 }
3929 if onuGemInfo != nil {
3930 if len(onuGemInfo.UniPorts) == 0 {
3931 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3932 return nil, err
3933 }
3934 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3935 return onuGemInfo, nil
3936 }
3937 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3938 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3939}
3940
3941func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3942 var err error
3943 var allocStats *oop.OnuAllocIdStatistics
3944 var onuGemStats *oop.GemPortStatistics
3945 for _, uni := range onuGemInfo.UniPorts {
3946 uniID := plt.UniIDFromPortNum(uni)
3947 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3948 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3949 if len(tpIDs) == 0 {
3950 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3951 continue
3952 }
3953 for _, tpId := range tpIDs {
3954 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3955 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3956 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3957 if techProfileInstance != nil {
3958 switch tpInst := techProfileInstance.(type) {
3959 case *tp_pb.TechProfileInstance:
3960 allocId := tpInst.UsScheduler.AllocId
3961 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3962 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3963 if err != nil {
3964 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3965 return err
3966 }
3967 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3968 allocIdInfo.AllocId = allocStats.AllocId
3969 allocIdInfo.RxBytes = allocStats.RxBytes
3970
3971 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3972
3973 gemPorts := tpInst.UpstreamGemPortAttributeList
3974 for _, gem := range gemPorts {
3975 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3976 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
3977 if err != nil {
3978 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
3979 return err
3980 }
3981 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
3982 gemStatsInfo.GemId = onuGemStats.GemportId
3983 gemStatsInfo.RxBytes = onuGemStats.RxBytes
3984 gemStatsInfo.RxPackets = onuGemStats.RxPackets
3985 gemStatsInfo.TxBytes = onuGemStats.TxBytes
3986 gemStatsInfo.TxPackets = onuGemStats.TxPackets
3987
3988 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
3989 }
3990 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
3991
3992 default:
3993 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
3994 return err
3995 }
3996 } else {
3997 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
3998 continue
3999 }
4000 }
4001 }
4002 return err
4003}
4004
4005//nolint:unparam
4006func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4007 singleValResp := extension.SingleGetValueResponse{
4008 Response: &extension.GetValueResponse{
4009 Status: extension.GetValueResponse_OK,
4010 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4011 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4012 },
4013 },
4014 }
4015 errResp := func(status extension.GetValueResponse_Status,
4016 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4017 return &extension.SingleGetValueResponse{
4018 Response: &extension.GetValueResponse{
4019 Status: status,
4020 ErrReason: reason,
4021 },
4022 }
4023 }
4024
4025 var intfID, onuID uint32
4026 if onuDevice != nil {
4027 onuID = onuDevice.ProxyAddress.OnuId
4028 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4029 }
4030
4031 onuKey := dh.formOnuKey(intfID, onuID)
4032 if _, ok := dh.onus.Load(onuKey); !ok {
4033 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4034 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4035 }
4036 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4037
4038 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4039 if err == nil {
4040 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4041 if err != nil {
4042 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4043 }
4044 } else {
4045 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4046 }
4047 return &singleValResp
4048}
4049
nikesh.krishnanc8473432023-06-14 12:14:54 +05304050func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304051 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
4052 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
4053 if err != nil {
4054 return nil, err
4055 }
4056 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304057}
4058
4059func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304060 Intf := oop.Interface{IntfId: intfID}
4061 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
4062 if err != nil {
4063 return nil, err
4064 }
4065 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304066}
4067
Gamze Abaka85e9a142021-05-26 13:41:39 +00004068func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004069 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
4070 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4071 if err != nil {
4072 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4073 return generateSingleGetValueErrorResponse(err)
4074 }
4075 return &extension.SingleGetValueResponse{
4076 Response: &extension.GetValueResponse{
4077 Status: extension.GetValueResponse_OK,
4078 Response: &extension.GetValueResponse_RxPower{
4079 RxPower: &extension.GetRxPowerResponse{
4080 IntfId: rxPowerRequest.IntfId,
4081 OnuId: rxPowerRequest.OnuId,
4082 Status: rxPower.Status,
4083 FailReason: rxPower.FailReason.String(),
4084 RxPower: rxPower.RxPowerMeanDbm,
4085 },
4086 },
4087 },
4088 }
4089}
4090
praneeth nalmas55616d62023-02-06 09:19:18 +05304091func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304092 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304093 return &extension.SingleGetValueResponse{
4094 Response: &extension.GetValueResponse{
4095 Status: status,
4096 ErrReason: reason,
4097 },
4098 }
4099 }
4100
4101 resp := extension.SingleGetValueResponse{
4102 Response: &extension.GetValueResponse{
4103 Status: extension.GetValueResponse_OK,
4104 Response: &extension.GetValueResponse_OltRxPower{
4105 OltRxPower: &extension.GetOltRxPowerResponse{},
4106 },
4107 },
4108 }
4109
4110 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4111 portLabel := OltRxPowerRequest.PortLabel
4112 serialNumber := OltRxPowerRequest.OnuSn
4113
4114 portInfo := strings.Split(portLabel, "-")
4115 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4116
4117 if err != nil {
4118 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4119 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4120 }
4121
4122 if portInfo[0] != "pon" {
4123 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4124 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4125 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304126
4127 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304128 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4129 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304130 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
4131 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4132 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304133 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4134 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304135 }
4136
4137 rxPowerValue := extension.RxPower{}
4138 rxPowerValue.OnuSn = onuDev.serialNumber
4139 rxPowerValue.Status = rxPower.GetStatus()
4140 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4141 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4142
4143 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304144 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304145 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4146 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4147 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304148 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304149 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304150 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304151 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05304152 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4153 if err != nil {
4154 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4155 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304156 rxPowerValue := extension.RxPower{}
4157 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4158 rxPowerValue.Status = rxPower.GetStatus()
4159 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4160 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4161
4162 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4163 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304164 }
4165 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4166 return true
4167 })
4168 }
4169 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4170 return &resp
4171}
4172
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304173func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4174 errResp := func(status extension.GetValueResponse_Status,
4175 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4176 return &extension.SingleGetValueResponse{
4177 Response: &extension.GetValueResponse{
4178 Status: status,
4179 ErrReason: reason,
4180 },
4181 }
4182 }
4183
4184 resp := extension.SingleGetValueResponse{
4185 Response: &extension.GetValueResponse{
4186 Status: extension.GetValueResponse_OK,
4187 Response: &extension.GetValueResponse_OltPonStatsResponse{
4188 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4189 },
4190 },
4191 }
4192
4193 portLabel := ponStatsRequest.GetPortLabel()
4194 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4195
4196 portInfo := strings.Split(portLabel, "-")
4197 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4198
4199 if err != nil {
4200 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4201 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4202 }
4203
4204 if portInfo[0] != "pon" {
4205 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4206 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4207 }
4208
4209 Interface := oop.Interface{IntfId: uint32(portNumber)}
4210 ponStats, err := dh.Client.GetPonPortStatistics(ctx, &Interface)
4211 if err != nil {
4212 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4213 return generateSingleGetValueErrorResponse(err)
4214 }
4215
4216 ponPortStats := resp.Response.GetOltPonStatsResponse()
4217 ponPortStats.PonPort = uint32(portNumber)
4218 ponPortStats.PortStatistics = ponStats
4219
4220 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4221 return &resp
4222}
4223
4224func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4225 errResp := func(status extension.GetValueResponse_Status,
4226 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4227 return &extension.SingleGetValueResponse{
4228 Response: &extension.GetValueResponse{
4229 Status: status,
4230 ErrReason: reason,
4231 },
4232 }
4233 }
4234
4235 resp := extension.SingleGetValueResponse{
4236 Response: &extension.GetValueResponse{
4237 Status: extension.GetValueResponse_OK,
4238 Response: &extension.GetValueResponse_OltNniStatsResponse{
4239 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4240 },
4241 },
4242 }
4243
4244 portLabel := nniStatsRequest.GetPortLabel()
4245 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4246
4247 portInfo := strings.Split(portLabel, "-")
4248 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4249
4250 if err != nil {
4251 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4252 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4253 }
4254
4255 if portInfo[0] != "nni" {
4256 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4257 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4258 }
4259
4260 Interface := oop.Interface{IntfId: uint32(portNumber)}
4261 nniStats, err := dh.Client.GetNniPortStatistics(ctx, &Interface)
4262 if err != nil {
4263 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4264 return generateSingleGetValueErrorResponse(err)
4265 }
4266
4267 nniPortStats := resp.Response.GetOltNniStatsResponse()
4268 nniPortStats.NniPort = uint32(portNumber)
4269 nniPortStats.PortStatistics = nniStats
4270
4271 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4272 return &resp
4273}
4274
Akash Kankanala041a2122024-10-16 15:49:22 +05304275// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004276func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304277 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004278 return &extension.SingleGetValueResponse{
4279 Response: &extension.GetValueResponse{
4280 Status: status,
4281 ErrReason: reason,
4282 },
4283 }
4284 }
4285
4286 if err != nil {
4287 if e, ok := status.FromError(err); ok {
4288 switch e.Code() {
4289 case codes.Internal:
4290 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4291 case codes.DeadlineExceeded:
4292 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4293 case codes.Unimplemented:
4294 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4295 case codes.NotFound:
4296 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4297 }
4298 }
4299 }
4300
4301 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4302}
khenaidoo106c61a2021-08-11 18:05:46 -04004303
4304/*
4305Helper functions to communicate with Core
4306*/
4307
4308func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4309 cClient, err := dh.coreClient.GetCoreServiceClient()
4310 if err != nil || cClient == nil {
4311 return nil, err
4312 }
4313 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4314 defer cancel()
4315 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4316}
4317
khenaidoodc2116e2021-10-19 17:33:19 -04004318func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004319 cClient, err := dh.coreClient.GetCoreServiceClient()
4320 if err != nil || cClient == nil {
4321 return nil, err
4322 }
4323 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4324 defer cancel()
4325 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4326}
4327
khenaidoodc2116e2021-10-19 17:33:19 -04004328func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004329 cClient, err := dh.coreClient.GetCoreServiceClient()
4330 if err != nil || cClient == nil {
4331 return err
4332 }
4333 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4334 defer cancel()
4335 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4336 return err
4337}
4338
4339func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4340 cClient, err := dh.coreClient.GetCoreServiceClient()
4341 if err != nil || cClient == nil {
4342 return nil, err
4343 }
4344 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4345 defer cancel()
4346 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4347}
4348
4349func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4350 cClient, err := dh.coreClient.GetCoreServiceClient()
4351 if err != nil || cClient == nil {
4352 return nil, err
4353 }
4354 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4355 defer cancel()
4356 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4357}
4358
4359func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4360 cClient, err := dh.coreClient.GetCoreServiceClient()
4361 if err != nil || cClient == nil {
4362 return err
4363 }
4364 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4365 defer cancel()
4366 _, err = cClient.DeviceUpdate(subCtx, device)
4367 return err
4368}
4369
khenaidoodc2116e2021-10-19 17:33:19 -04004370func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004371 cClient, err := dh.coreClient.GetCoreServiceClient()
4372 if err != nil || cClient == nil {
4373 return nil, err
4374 }
4375 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4376 defer cancel()
4377 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4378}
4379
khenaidoodc2116e2021-10-19 17:33:19 -04004380func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004381 cClient, err := dh.coreClient.GetCoreServiceClient()
4382 if err != nil || cClient == nil {
4383 return err
4384 }
4385 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4386 defer cancel()
4387 _, err = cClient.SendPacketIn(subCtx, pkt)
4388 return err
4389}
4390
4391func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4392 cClient, err := dh.coreClient.GetCoreServiceClient()
4393 if err != nil || cClient == nil {
4394 return err
4395 }
4396 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4397 defer cancel()
4398 _, err = cClient.PortCreated(subCtx, port)
4399 return err
4400}
4401
khenaidoodc2116e2021-10-19 17:33:19 -04004402func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004403 cClient, err := dh.coreClient.GetCoreServiceClient()
4404 if err != nil || cClient == nil {
4405 return err
4406 }
4407 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4408 defer cancel()
4409 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4410 return err
4411}
4412
khenaidoodc2116e2021-10-19 17:33:19 -04004413func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004414 cClient, err := dh.coreClient.GetCoreServiceClient()
4415 if err != nil || cClient == nil {
4416 return err
4417 }
4418 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4419 defer cancel()
4420 _, err = cClient.PortStateUpdate(subCtx, portState)
4421 return err
4422}
4423
khenaidoodc2116e2021-10-19 17:33:19 -04004424func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004425 cClient, err := dh.coreClient.GetCoreServiceClient()
4426 if err != nil || cClient == nil {
4427 return nil, err
4428 }
4429 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4430 defer cancel()
4431 return cClient.GetDevicePort(subCtx, portFilter)
4432}
4433
nikesh.krishnanc8473432023-06-14 12:14:54 +05304434func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4435 cClient, err := dh.coreClient.GetCoreServiceClient()
4436 if err != nil || cClient == nil {
4437 return nil, err
4438 }
4439 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4440 defer cancel()
4441 return cClient.GetPorts(subCtx, portFilter)
4442}
4443
khenaidoo106c61a2021-08-11 18:05:46 -04004444/*
4445Helper functions to communicate with child adapter
4446*/
4447
khenaidoodc2116e2021-10-19 17:33:19 -04004448func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004449 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4450 if err != nil || aClient == nil {
4451 return err
4452 }
4453 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4454 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4455 defer cancel()
4456 _, err = aClient.OmciIndication(subCtx, response)
4457 return err
4458}
4459
khenaidoodc2116e2021-10-19 17:33:19 -04004460func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004461 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4462 if err != nil || aClient == nil {
4463 return err
4464 }
4465 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4466 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4467 defer cancel()
4468 _, err = aClient.OnuIndication(subCtx, onuInd)
4469 return err
4470}
4471
khenaidoodc2116e2021-10-19 17:33:19 -04004472func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004473 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4474 if err != nil || aClient == nil {
4475 return err
4476 }
4477 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4478 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4479 defer cancel()
4480 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4481 return err
4482}
4483
khenaidoodc2116e2021-10-19 17:33:19 -04004484func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004485 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4486 if err != nil || aClient == nil {
4487 return err
4488 }
4489 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4490 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4491 defer cancel()
4492 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4493 return err
4494}
4495
khenaidoodc2116e2021-10-19 17:33:19 -04004496func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004497 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4498 if err != nil || aClient == nil {
4499 return err
4500 }
4501 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4502 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4503 defer cancel()
4504 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4505 return err
4506}
4507
4508/*
4509Helper functions for remote communication
4510*/
4511
4512// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4513// supports is deleted
4514func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4515 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4516
4517 dh.lockChildAdapterClients.Lock()
4518 defer dh.lockChildAdapterClients.Unlock()
4519 if _, ok := dh.childAdapterClients[endpoint]; ok {
4520 // Already set
4521 return nil
4522 }
4523
4524 // Setup child's adapter grpc connection
4525 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004526 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4527 dh.cfg.AdapterEndpoint,
4528 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004529 "onu_inter_adapter_service.OnuInterAdapterService",
4530 dh.onuInterAdapterRestarted,
4531 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004532 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4533 return err
4534 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304535 retryCodes := []codes.Code{
4536 codes.Unavailable, // server is currently unavailable
4537 codes.DeadlineExceeded, // deadline for the operation was exceeded
4538 }
4539 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4540 grpcRetryOptions := grpc_retry.UnaryClientInterceptor(grpc_retry.WithMax(dh.cfg.MaxRetries), grpc_retry.WithPerRetryTimeout(dh.cfg.PerRPCRetryTimeout), grpc_retry.WithCodes(retryCodes...), backoffCtxOption)
khenaidoo106c61a2021-08-11 18:05:46 -04004541
nikesh.krishnand9812542023-08-01 18:31:39 +05304542 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004543 // Wait until we have a connection to the child adapter.
4544 // Unlimited retries or until context expires
4545 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4546 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4547 for {
4548 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4549 if err == nil && client != nil {
4550 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4551 break
4552 }
4553 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4554 // Backoff
4555 if err = backoff.Backoff(subCtx); err != nil {
4556 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4557 break
4558 }
4559 }
4560 return nil
4561}
4562
khenaidoodc2116e2021-10-19 17:33:19 -04004563func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004564 // First check from cache
4565 dh.lockChildAdapterClients.RLock()
4566 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4567 dh.lockChildAdapterClients.RUnlock()
4568 return cgClient.GetOnuInterAdapterServiceClient()
4569 }
4570 dh.lockChildAdapterClients.RUnlock()
4571
4572 // Set the child connection - can occur on restarts
4573 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4574 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4575 cancel()
4576 if err != nil {
4577 return nil, err
4578 }
4579
4580 // Get the child client now
4581 dh.lockChildAdapterClients.RLock()
4582 defer dh.lockChildAdapterClients.RUnlock()
4583 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4584 return cgClient.GetOnuInterAdapterServiceClient()
4585 }
4586 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4587}
4588
4589func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4590 dh.lockChildAdapterClients.Lock()
4591 defer dh.lockChildAdapterClients.Unlock()
4592 for key, client := range dh.childAdapterClients {
4593 client.Stop(ctx)
4594 delete(dh.childAdapterClients, key)
4595 }
4596}
4597
khenaidooefff76e2021-12-15 16:51:30 -05004598// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4599func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4600 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004601 return nil
4602}
4603
khenaidooefff76e2021-12-15 16:51:30 -05004604// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4605func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4606 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004607 return nil
4608 }
khenaidooefff76e2021-12-15 16:51:30 -05004609 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004610}
Girish Gowdra950326e2021-11-05 12:43:24 -07004611
4612func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4613 dh.lockDevice.Lock()
4614 defer dh.lockDevice.Unlock()
4615 dh.isDeviceDeletionInProgress = flag
4616}
4617
4618func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4619 dh.lockDevice.RLock()
4620 defer dh.lockDevice.RUnlock()
4621 return dh.isDeviceDeletionInProgress
4622}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004623
4624// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4625// Returns false if waiting timed out.
4626func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4627 c := make(chan struct{})
4628 go func() {
4629 defer close(c)
4630 wg.Wait()
4631 }()
4632 select {
4633 case <-c:
4634 return true // completed normally
4635 case <-time.After(timeout):
4636 return false // timed out
4637 }
4638}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304639
4640func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4641 val, err := json.Marshal(signature)
4642 if err != nil {
4643 logger.Error(ctx, "failed-to-marshal")
4644 return
4645 }
4646 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4647 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4648 }
4649}
4650
4651func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4652 var signature uint32
4653
4654 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4655 if er == nil {
4656 if Value != nil {
4657 Val, er := kvstore.ToByte(Value.Value)
4658 if er != nil {
4659 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4660 return signature
4661 }
4662 if er = json.Unmarshal(Val, &signature); er != nil {
4663 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4664 return signature
4665 }
4666 }
4667 }
4668 return signature
4669}