blob: b8be44b95ad43f9778c362e06d654c50d4596911 [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"
Abhay Kumard3f18512025-12-09 07:51:12 +000042 grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
khenaidoo106c61a2021-08-11 18:05:46 -040043 "github.com/opencord/voltha-lib-go/v7/pkg/config"
44 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
45 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
46 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070047 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040048 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080049
nikesh.krishnand9812542023-08-01 18:31:39 +053050 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
khenaidoo106c61a2021-08-11 18:05:46 -040051 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053052 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080053 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040056 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040057 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
58 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040059 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
60 oop "github.com/opencord/voltha-protos/v5/go/openolt"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +053061 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
khenaidoo106c61a2021-08-11 18:05:46 -040062 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070063 "google.golang.org/grpc"
nikesh.krishnand9812542023-08-01 18:31:39 +053064 codes "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040065 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053066)
67
salmansiddiqui7ac62132019-08-22 03:58:50 +000068// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040069const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080070 InvalidPort = 0xffffffff
71 MaxNumOfGroupHandlerChannels = 256
72
73 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
74 McastFlowOrGroupModify = "McastFlowOrGroupModify"
75 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050076 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010077
78 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053079 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040080)
81
Mahir Gunyela2e68702022-12-07 00:00:42 -080082// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053083type DeviceHandler struct {
Akash Kankanala041a2122024-10-16 15:49:22 +053084 EventProxy eventif.EventProxy
85 Client oop.OpenoltClient
86 cm *config.ConfigManager
87 device *voltha.Device
88 cfg *conf.AdapterFlags
89 coreClient *vgrpc.Client
90 childAdapterClients map[string]*vgrpc.Client
91 openOLT *OpenOLT
92 exitChannel chan struct{}
93 transitionMap *TransitionMap
94 clientCon *grpc.ClientConn
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070098
99 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530100
Akash Kankanala041a2122024-10-16 15:49:22 +0530101 portStats *OpenOltStatisticsMgr
102 metrics *pmmetrics.PmMetrics
103 stopCollector chan bool
104 stopHeartbeatCheck chan bool
105 stopIndications chan bool
106 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
107
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700108 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
109 // if the value is true that means the OnuDiscovery indication
110 // is currently being processed and thus we can ignore concurrent requests
111 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
112 // if we do it means something went wrong and we need to retry
Akash Kankanala041a2122024-10-16 15:49:22 +0530113 discOnus sync.Map
114 onus sync.Map
115 activePorts sync.Map
116 flowMgr []*OpenOltFlowMgr
117 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra491a9c62021-01-06 16:43:07 -0800118
119 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
120 // 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 -0700121 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
122 stopMcastHandlerRoutine []chan bool
123 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000124
Akash Kankanala041a2122024-10-16 15:49:22 +0530125 lockChildAdapterClients sync.RWMutex
126 lockDevice sync.RWMutex
127 perPonOnuIndicationChannelLock sync.Mutex
128
129 totalPonPorts uint32
130 heartbeatSignature uint32
131 isCollectorActive bool
132 isHeartbeatCheckActive bool
133 isReadIndicationRoutineActive bool
134
Gamze Abakac2c32a62021-03-11 11:44:18 +0000135 adapterPreviouslyConnected bool
136 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700137
138 isDeviceDeletionInProgress bool
Nandita Biradar1b590f12024-09-27 10:56:28 +0530139 prevOperStatus common.OperStatus_Types
bseenivaaa9165b2025-09-18 17:28:12 +0530140 collectorWaitGroup sync.WaitGroup
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +0000141 transitionHandlerCancel context.CancelFunc
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700142}
143
Mahir Gunyela2e68702022-12-07 00:00:42 -0800144// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700145type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400146 deviceID string
147 deviceType string
148 serialNumber string
Akash Kankanala041a2122024-10-16 15:49:22 +0530149 proxyDeviceID string
150 adapterEndpoint string
khenaidoo106c61a2021-08-11 18:05:46 -0400151 onuID uint32
152 intfID uint32
khenaidoo106c61a2021-08-11 18:05:46 -0400153 losRaised bool
154 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700155}
156
Mahir Gunyelb0046752021-02-26 13:51:05 -0800157type onuIndicationMsg struct {
158 ctx context.Context
159 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800160}
161
162type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800163 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800164 stopChannel chan struct{}
165}
166
Mahir Gunyela2e68702022-12-07 00:00:42 -0800167// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
168// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
169// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
170// 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 -0800171type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400172 ctx context.Context // Flow/group handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400173 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
174 group *of.OfpGroupEntry // Group message (can be nil or valid group)
175 errChan *chan error // channel to report the mcast Flow/group handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530176 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
Girish Gowdra491a9c62021-01-06 16:43:07 -0800177}
178
Naga Manjunath7615e552019-10-11 22:35:47 +0530179var pmNames = []string{
180 "rx_bytes",
181 "rx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530182 "rx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530183 "rx_mcast_packets",
184 "rx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530185 "rx_error_packets",
186 "rx_crc_errors",
187 "rx_packets_dropped",
Naga Manjunath7615e552019-10-11 22:35:47 +0530188 "tx_bytes",
189 "tx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530190 "tx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530191 "tx_mcast_packets",
192 "tx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530193 "tx_error_packets",
194 "tx_dropped_total",
Naga Manjunath7615e552019-10-11 22:35:47 +0530195}
196
Mahir Gunyela2e68702022-12-07 00:00:42 -0800197// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400198func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700199 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700200 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700201 device.deviceType = deviceTp
202 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700203 device.onuID = onuID
204 device.intfID = intfID
205 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530206 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400207 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700208 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530209}
210
Mahir Gunyela2e68702022-12-07 00:00:42 -0800211// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400212func 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 -0700213 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530214 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800215 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400216 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400217 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700219 dh.device = cloned
220 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500221 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700222 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000223 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
224 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530225 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 -0500226 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800227 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800228 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400229 dh.childAdapterClients = make(map[string]*vgrpc.Client)
230 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300231 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530232 if dh.kvStore == nil {
233 logger.Error(ctx, "Failed to setup KV store")
234 return nil
235 }
236
Girish Gowdra491a9c62021-01-06 16:43:07 -0800237 // Create a slice of buffered channels for handling concurrent mcast flow/group.
238 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700239 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
240 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800241 for i := range dh.incomingMcastFlowOrGroup {
242 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800243 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800244 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
245 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
246 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
247 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700248 dh.mcastHandlerRoutineActive[i] = true
249 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800250 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530251 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700252 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530253}
254
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530255func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
256 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
257 switch storeType {
258 case "etcd":
259 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530260 case "redis":
261 return kvstore.NewRedisClient(address, timeout, false)
262 case "redis-sentinel":
263 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530264 }
265 return nil, errors.New("unsupported-kv-store")
266}
267
268// SetKVClient sets the KV client and return a kv backend
269func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
270 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
271 if err != nil {
272 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
273 return nil
274 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530275 kvbackend := &db.Backend{
276 Client: kvClient,
277 StoreType: backend,
278 Address: addr,
279 Timeout: rsrcMgr.KvstoreTimeout,
280 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
281
282 return kvbackend
283}
284
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000285// CloseKVClient closes open KV clients
Abhay Kumarb87ac882025-10-30 09:55:07 +0000286// This method is thread-safe and can be called concurrently
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000287func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
Abhay Kumarb87ac882025-10-30 09:55:07 +0000288 // Acquire read lock to safely iterate over resourceMgr and flowMgr slices
289 // Use RLock since we're only reading the slices, not modifying them
290 dh.lockDevice.RLock()
291 defer dh.lockDevice.RUnlock()
292
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000293 if dh.resourceMgr != nil {
294 for _, rscMgr := range dh.resourceMgr {
295 if rscMgr != nil {
296 rscMgr.CloseKVClient(ctx)
297 }
298 }
299 }
300 if dh.flowMgr != nil {
301 for _, flMgr := range dh.flowMgr {
302 if flMgr != nil {
303 flMgr.CloseKVClient(ctx)
304 }
305 }
306 }
307}
308
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530309// start save the device to the data model
310func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700311 dh.lockDevice.Lock()
312 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000313 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700314 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000315 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530316}
317
khenaidooefff76e2021-12-15 16:51:30 -0500318// Stop stops the device handler
319func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700320 dh.lockDevice.Lock()
321 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000322 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500323 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400324
khenaidooefff76e2021-12-15 16:51:30 -0500325 // Delete (which will stop also) all grpc connections to the child adapters
326 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000327 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530328}
329
ssiddiqui04386ee2021-08-23 21:58:25 +0530330func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
331 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
332 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
333 if pooledIntfID == intfID {
334 return resourceRanges.GetTechnology()
335 }
336 }
337 }
338 return ""
339}
340
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400341func macifyIP(ip net.IP) string {
342 if len(ip) > 0 {
343 oct1 := strconv.FormatInt(int64(ip[12]), 16)
344 oct2 := strconv.FormatInt(int64(ip[13]), 16)
345 oct3 := strconv.FormatInt(int64(ip[14]), 16)
346 oct4 := strconv.FormatInt(int64(ip[15]), 16)
347 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
348 }
349 return ""
350}
351
Neha Sharma96b7bf22020-06-15 10:37:32 +0000352func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400353 var genmac string
354 var addr net.IP
355 var ips []string
356 var err error
357
Neha Sharma96b7bf22020-06-15 10:37:32 +0000358 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400359
360 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000361 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400362
363 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000364 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400365 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000366 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400367 }
368 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000369 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530370 log.Fields{"host": ips[0],
371 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400372 return genmac, nil
373 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000374 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400375 }
376
377 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000378 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530379 log.Fields{"host": host,
380 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400381 return genmac, nil
382}
383
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530384func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700385 slist := strings.Split(mac, ":")
386 result := make([]uint32, len(slist))
387 var err error
388 var tmp int64
389 for index, val := range slist {
390 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
391 return []uint32{1, 2, 3, 4, 5, 6}
392 }
393 result[index] = uint32(tmp)
394 }
395 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530396}
397
Mahir Gunyela2e68702022-12-07 00:00:42 -0800398// 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 -0800399func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800400 switch portType {
401 case voltha.Port_ETHERNET_NNI:
402 return fmt.Sprintf("nni-%d", portNum), nil
403 case voltha.Port_PON_OLT:
404 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700405 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800406
Girish Kumarf26e4882020-03-05 06:49:10 +0000407 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530408}
409
Elia Battiston596406d2022-02-02 12:19:00 +0100410func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
411 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530412 // In case it was not set in the indication
413 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100414 speedMbps = defaultPortSpeedMbps
415 }
416
417 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
418 switch speedMbps {
419 case 1000000:
420 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
421 case 100000:
422 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
423 case 40000:
424 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
425 case 10000:
426 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
427 case 1000:
428 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
429 case 100:
430 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
431 case 10:
432 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
433 }
434
435 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
436
437 port := &of.OfpPort{
438 HwAddr: macAddressToUint32Array(macAddress),
439 Config: 0,
440 State: uint32(of.OfpPortState_OFPPS_LIVE),
441 Curr: capacity,
442 Advertised: capacity,
443 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530444 CurrSpeed: speedMbps * 1000, // kbps
445 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100446 }
447
448 return port
449}
450
451func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000452 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700453 if state == "up" {
454 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530455 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500456 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700457 } else {
458 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500459 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700460 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700461 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400462 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800463 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000464 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400465 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500466
khenaidoo106c61a2021-08-11 18:05:46 -0400467 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400468 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400469 DeviceId: dh.device.Id,
470 Port: portNum,
471 })
472 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000473 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400474 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400475 DeviceId: dh.device.Id,
476 PortType: portType,
477 PortNo: portNum,
478 OperStatus: operStatus})
479 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400480 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
481 "device-id": dh.device.Id,
482 "port-type": portType,
483 "port-number": portNum,
484 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500485 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400486 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500487 }
khenaidoo106c61a2021-08-11 18:05:46 -0400488
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400489 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400490 port = &voltha.Port{
491 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700492 PortNo: portNum,
493 Label: label,
494 Type: portType,
495 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100496 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700497 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700499 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400500 err = dh.createPortInCore(ctx, port)
501 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000502 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800503 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000504 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400505 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530507 return nil
508}
509
Kent Hagermane6ff1012020-07-14 15:07:53 -0400510func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400511 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530512 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400513 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
514 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530515 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800516 dh.lockDevice.Lock()
517 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530518 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530519}
520
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700521// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530522// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800523func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000524 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700525 defer func() {
526 dh.lockDevice.Lock()
527 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530528 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700529 dh.lockDevice.Unlock()
530 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700531 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700532 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700533 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700534 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400535
David Bainbridgef5879ca2019-12-13 21:17:54 +0000536 // Create an exponential backoff around re-enabling indications. The
537 // maximum elapsed time for the back off is set to 0 so that we will
538 // continue to retry. The max interval defaults to 1m, but is set
539 // here for code clarity
540 indicationBackoff := backoff.NewExponentialBackOff()
541 indicationBackoff.MaxElapsedTime = 0
542 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700543
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700544 dh.lockDevice.Lock()
545 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530546 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700547 dh.lockDevice.Unlock()
548
Girish Gowdra3f974912020-03-23 20:35:18 -0700549Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700550 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400551 select {
552 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000553 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700554 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400555 default:
556 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100557
558 select {
559 case <-indications.Context().Done():
560 if err != nil {
561 logger.Warnw(ctx, "error-during-enable-indications",
562 log.Fields{"err": err,
563 "device-id": dh.device.Id})
564 }
565
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400566 // Use an exponential back off to prevent getting into a tight loop
567 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100568 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
569 "device-id": dh.device.Id,
570 "duration": duration,
571 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400572 if duration == backoff.Stop {
573 // If we reach a maximum then warn and reset the backoff
574 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100575 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530576 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530577 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400578 indicationBackoff.Reset()
579 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700580
581 // On failure process a backoff timer while watching for stopIndications
582 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700583 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700584 select {
585 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000586 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700587 if !backoffTimer.Stop() {
588 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700589 }
590 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700591 case <-backoffTimer.C:
592 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700593 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700594 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
595 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400596 }
597 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100598 default:
599 if err != nil {
600 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530601 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530602 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100603 // Close the stream, and re-initialize it
604 if err = indications.CloseSend(); err != nil {
605 // Ok to ignore here, because we landed here due to a problem on the stream
606 // In all probability, the closeSend call may fail
607 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
608 log.Fields{"err": err,
609 "device-id": dh.device.Id})
610 }
611 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
612 return err
613 }
614 // once we re-initialized the indication stream, continue to read indications
615 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700616 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100617 // Reset backoff if we have a successful receive
618 indicationBackoff.Reset()
619 // When OLT is admin down, ignore all indications.
620 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
621 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
622 log.Fields{"indication": indication,
623 "device-id": dh.device.Id})
624 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700625 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100626 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530627 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700628 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700630 // Close the send stream
631 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700632
Girish Gowdra3f974912020-03-23 20:35:18 -0700633 return nil
634}
635
636func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700637 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700638 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
639 if err != nil {
640 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
641 }
642 if indications == nil {
643 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
644 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700645 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700646 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400647}
648
649// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
650func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
651 switch indication.Data.(type) {
652 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
653 return true
654
655 default:
656 return false
657 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658}
659
David K. Bainbridge794735f2020-02-11 21:01:37 -0800660func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700661 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000662 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530663 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700664 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530665 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000667 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000668 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530669 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000670 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000672 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800673 }
674 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700675}
676
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530677func (dh *DeviceHandler) handleOnuDisableIndication(ctx context.Context, onuIndication *oop.OnuDisabledIndication) error {
678 logger.Infow(ctx, "handleOnuDisableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
679 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
680 intfID := onuIndication.GetIntfId()
681 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
682 onuDev := dh.getChildDevice(ctx, sn, ponPort)
683 if onuDev == nil {
684 logger.Warnw(ctx, "handleOnuDisableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
685 onuDev = &OnuDevice{
686 serialNumber: sn,
687 }
688 }
689 dh.discOnus.Delete(sn)
690
691 raisedTs := time.Now().Unix()
692 if err := dh.eventMgr.onuDisableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
693 return olterrors.NewErrAdapter("failed-indication", log.Fields{
694 "device-id": dh.device.Id,
695 "indication": onuIndication,
696 "timestamp": raisedTs}, err)
697 }
698 OnuIndication := generateOnuIndication(onuDev.intfID, onuDev.onuID, "down", "down")
699 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDev.adapterEndpoint, &ia.OnuIndicationMessage{
700 DeviceId: onuDev.deviceID,
701 OnuIndication: OnuIndication.GetOnuInd(),
702 })
703 if err != nil {
704 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
705 "onu-indicator": OnuIndication.GetOnuInd(),
706 "source": dh.openOLT.config.AdapterEndpoint,
707 "device-type": onuDev.deviceType,
708 "device-id": onuDev.deviceID}, err)
709 }
710 return nil
711}
712
713func (dh *DeviceHandler) handleOnuEnableIndication(ctx context.Context, onuIndication *oop.OnuEnabledIndication) error {
714 logger.Infow(ctx, "handleOnuEnableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
715 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
716 intfID := onuIndication.GetIntfId()
717 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
718 onuDev := dh.getChildDevice(ctx, sn, ponPort)
719 if onuDev == nil {
720 logger.Warnw(ctx, "handleOnuEnableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
721 onuDev = &OnuDevice{
722 serialNumber: sn,
723 }
724 }
725 raisedTs := time.Now().Unix()
726
727 if err := dh.eventMgr.onuEnableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
728 return olterrors.NewErrAdapter("failed-indication", log.Fields{
729 "device-id": dh.device.Id,
730 "indication": onuIndication,
731 "timestamp": raisedTs}, err)
732 }
733 return nil
734}
735
Akash Kankanala041a2122024-10-16 15:49:22 +0530736// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530737func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700738 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 switch indication.Data.(type) {
740 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000741 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
742 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700743 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 -0800744 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400745 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800746 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000748 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
749 defer span.Finish()
750
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800752 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100753 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400754 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800755 }
756 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000757 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000759 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
760 defer span.Finish()
761
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762 intfOperInd := indication.GetIntfOperInd()
763 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800764 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100765 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400766 _ = 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 -0800767 }
768 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 } else if intfOperInd.GetType() == "pon" {
770 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
771 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800772 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100773 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400774 _ = 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 -0800775 }
776 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000777 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700778 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000779 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530780 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530781 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000783 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
784 defer span.Finish()
785
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700786 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000787 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530788 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800789 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700790 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000791 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
792 defer span.Finish()
793
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700794 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000795 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530796 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800797 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700798 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000799 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
800 defer span.Finish()
801
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700802 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000803 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 -0800804 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000805 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400806 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800807 }
808 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700809 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000810 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
811 defer span.Finish()
812
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700813 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000814 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700815 "intf-type": pktInd.IntfId,
816 "intf-id": pktInd.IntfId,
817 "gem-port-id": pktInd.GemportId,
818 "port-no": pktInd.PortNo,
819 "device-id": dh.device.Id,
820 })
821
822 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000823 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700824 "intf-type": pktInd.IntfId,
825 "intf-id": pktInd.IntfId,
826 "gem-port-id": pktInd.GemportId,
827 "port-no": pktInd.PortNo,
828 "packet": hex.EncodeToString(pktInd.Pkt),
829 "device-id": dh.device.Id,
830 })
831 }
832
David K. Bainbridge794735f2020-02-11 21:01:37 -0800833 go func() {
834 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400835 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800836 }
837 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700838 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000839 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
840 defer span.Finish()
841
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700843 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000845 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
846 defer span.Finish()
847
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700848 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700850 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000851 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
852 defer span.Finish()
853
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700854 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000855 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
856 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530857 case *oop.Indication_OnuDisabledInd:
858 span, ctx := log.CreateChildSpan(ctx, "onu-disable-indication", log.Fields{"device-id": dh.device.Id})
859 defer span.Finish()
860 logger.Infow(ctx, "received onu-disable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
861 if err := dh.handleOnuDisableIndication(ctx, indication.GetOnuDisabledInd()); err != nil {
862 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
863 }
864 case *oop.Indication_OnuEnabledInd:
865 span, ctx := log.CreateChildSpan(ctx, "onu-enable-indication", log.Fields{"device-id": dh.device.Id})
866 defer span.Finish()
867 logger.Infow(ctx, "received onu-enable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
868 if err := dh.handleOnuEnableIndication(ctx, indication.GetOnuEnabledInd()); err != nil {
869 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
870 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700871 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530872}
873
nikesh.krishnanc8473432023-06-14 12:14:54 +0530874func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
875 onuInd := &oop.OnuIndication{
876 IntfId: intfID,
877 OnuId: onuID,
878 OperState: operState,
879 AdminState: adminState,
880 }
881 indication := &oop.Indication{
882 Data: &oop.Indication_OnuInd{
883 OnuInd: onuInd,
884 },
885 }
886 return indication
887}
888
889func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
890 onuAlarmInd := &oop.OnuAlarmIndication{
891 IntfId: intfID,
892 OnuId: onuID,
893 LosStatus: losStatus,
894 }
895 alarmInd := &oop.AlarmIndication{
896 Data: &oop.AlarmIndication_OnuAlarmInd{
897 OnuAlarmInd: onuAlarmInd,
898 },
899 }
900 return alarmInd
901}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530902
Akash Kankanala041a2122024-10-16 15:49:22 +0530903func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530904 ponlosAlarmInd := &oop.LosIndication{
905 IntfId: intfID,
906 Status: losStatus,
907 }
908 alarmInd := &oop.AlarmIndication{
909 Data: &oop.AlarmIndication_LosInd{
910 LosInd: ponlosAlarmInd,
911 },
912 }
913 return alarmInd
914}
Akash Kankanala041a2122024-10-16 15:49:22 +0530915
nikesh.krishnanc8473432023-06-14 12:14:54 +0530916func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
917 go func() {
918 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
919 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
920 }
921 }()
922
923 raisedTs := time.Now().Unix()
924 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
925}
926
927func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530928 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
929 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530930 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530931 return err
932 }
933 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530934 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
935 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
936 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
937
938 onuID := onuDeviceFromCore.ProxyAddress.OnuId
939 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
940 if err != nil {
941 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530942 } else {
943 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
944 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
945 switch {
946 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
947 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
948 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
949
950 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530951 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530952 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
953 raisedTs := time.Now().Unix()
954 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
955
956 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
957 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530958 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530959 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530960 return nil
961}
962
963func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
964 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
965 DeviceId: dh.device.Id,
966 PortType: voltha.Port_PON_OLT,
967 })
968 if err != nil {
969 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530970 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530971 }
972 for _, portFromCore := range portsFromCore.Items {
973 portNum := portFromCore.GetPortNo()
974 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
975 portOperStatusFromCore := portFromCore.OperStatus
976 portAdminStateFromCore := portFromCore.AdminState
977 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
978 if err != nil {
979 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
980 } else {
981 portLosFromOlt := ponPortFromOlt.GetLos()
982 portStateFromOlt := ponPortFromOlt.GetState()
983 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
984 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
985 "portStateFromOlt": portStateFromOlt.String(),
986 "portOperStatusFromCore": portOperStatusFromCore.String(),
987 "device-id": dh.device.Id,
988 "port": portNum})
989 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
990 raisedTs := time.Now().Unix()
991 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530992 }
993 switch {
994 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
995 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
996 "portStateFromOlt": portStateFromOlt.String(),
997 "portOperStatusFromCore": portOperStatusFromCore.String(),
998 "device-id": dh.device.Id,
999 "port": portNum})
1000 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
1001 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
1002 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
1003 "portStateFromOlt": portStateFromOlt.String(),
1004 "portOperStatusFromCore": portOperStatusFromCore.String(),
1005 "device-id": dh.device.Id,
1006 "port": portNum})
1007 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
1008 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
1009 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
1010 "device-id": dh.device.Id,
1011 "port": portNum})
1012 default:
1013 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
1014 "portStateFromOlt": portStateFromOlt.String(),
1015 "portOperStatusFromCore": portOperStatusFromCore.String(),
1016 "device-id": dh.device.Id,
1017 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301018 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301019 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301020 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301021 return nil
1022}
1023
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301024// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301025func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +05301026 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +05301027 // Declare deviceStateFilter to be used later
1028 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +05301029 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001030 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +05301031 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301032 if err != nil {
1033 return fmt.Errorf("failed to get device from core: %w", err)
1034 }
1035 logger.Info(ctx, "Device state", log.Fields{
1036 "device-id": device.Id,
1037 "CurrOperStatus": device.OperStatus,
1038 "CurrConnStatus": device.ConnectStatus,
1039 })
1040 // Perform cleanup if the device's operational status is REBOOTED
1041 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
1042 // Log the device's operational status if it's REBOOTED
1043 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
1044 "device-id": device.Id,
1045 "OperStatus": device.OperStatus,
1046 })
1047 dh.lockDevice.RLock()
1048 // Stop the read indication only if it the routine is active
1049 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1050 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1051 // on next execution of the readIndication routine.
1052 if dh.isHeartbeatCheckActive {
1053 dh.stopHeartbeatCheck <- true
1054 }
1055 if dh.isReadIndicationRoutineActive {
1056 dh.stopIndications <- true
1057 }
bseenivaaa9165b2025-09-18 17:28:12 +05301058 if dh.isCollectorActive {
1059 dh.stopCollector <- true
1060 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301061 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +05301062 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301063 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
1064 return fmt.Errorf("cleanup device resources failed: %w", err)
1065 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301066 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301067 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1068 }
bseenivaaa9165b2025-09-18 17:28:12 +05301069 dh.collectorWaitGroup.Add(1)
1070 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301071 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301072 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +05301073 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
1074 // Log the device's operational status if it's RECONCILING
1075 logger.Info(ctx, "Device is being reconciled", log.Fields{
1076 "device-id": device.Id,
1077 "OperStatus": device.OperStatus,
1078 })
1079
1080 // Perform reconciliation steps
1081 err = dh.reconcileOnus(ctx)
1082 if err != nil {
1083 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1084 }
1085 err = dh.reconcilePonPorts(ctx)
1086 if err != nil {
1087 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301088 }
1089 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001090 // instantiate the mcast handler routines.
1091 for i := range dh.incomingMcastFlowOrGroup {
1092 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1093 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1094 if !dh.mcastHandlerRoutineActive[i] {
1095 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1096 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1097 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1098 // for incoming mcast flow/group to be processed serially.
1099 dh.mcastHandlerRoutineActive[i] = true
1100 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1101 }
1102 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301103 // Create DeviceStateFilter with the desired operational and connection statuses
1104 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001105 DeviceId: dh.device.Id,
1106 OperStatus: voltha.OperStatus_ACTIVE,
1107 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301108 }
1109 // Log DeviceStateFilter for debugging purposes
1110 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1111 "DeviceId": deviceStateFilter.DeviceId,
1112 "OperStatus": deviceStateFilter.OperStatus,
1113 "ConnStatus": deviceStateFilter.ConnStatus,
1114 })
1115 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301116 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001117 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001118 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001119
Akash Kankanala041a2122024-10-16 15:49:22 +05301120 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001121 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1122 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301123
1124 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1125 if err != nil {
1126 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1127 }
1128 dh.populateActivePorts(ctx, ports.Items)
1129 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1130 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1131 }
1132
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001133 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001134 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1135
Girish Gowdru0c588b22019-04-23 23:24:56 -04001136 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301137}
1138
1139// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301140func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001141 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001142
khenaidoo106c61a2021-08-11 18:05:46 -04001143 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001144 if err != nil || device == nil {
1145 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001146 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001147 }
1148
1149 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001150
Akash Kankanala041a2122024-10-16 15:49:22 +05301151 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001152 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001153 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001154 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001155 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001156
khenaidoodc2116e2021-10-19 17:33:19 -04001157 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001158 DeviceId: cloned.Id,
1159 OperStatus: cloned.OperStatus,
1160 ConnStatus: cloned.ConnectStatus,
1161 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001162 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001163 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001164
Akash Kankanala041a2122024-10-16 15:49:22 +05301165 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001166 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001167 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001168 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001169 }
1170 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001171 // Update onu state as down in onu adapter
1172 onuInd := oop.OnuIndication{}
1173 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001174
1175 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1176 if err != nil {
1177 return err
1178 }
1179 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001180 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001181 DeviceId: onuDevice.Id,
1182 OnuIndication: &onuInd,
1183 })
1184 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001185 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001186 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001187 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001188 "onu-indicator": onuInd,
1189 "device-type": onuDevice.Type,
1190 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301191 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001192 } else {
1193 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 -07001194 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001195 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001196 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001197 /* Discovered ONUs entries need to be cleared , since after OLT
1198 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301199 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001200 dh.lockDevice.Unlock()
1201
Neha Sharma96b7bf22020-06-15 10:37:32 +00001202 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001203 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301204}
1205
1206// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301207func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001208 var err error
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001209 dh.lockDevice.RLock()
1210 hostAndPort := dh.device.GetHostAndPort() //store the IP of OLT , so that when we are blocked on grpc dail with old IP,and IP is updated it wont be updated here.
1211 dh.lockDevice.RUnlock()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001212 // if the connection is already available, close the previous connection (olt reboot case)
1213 if dh.clientCon != nil {
1214 if err = dh.clientCon.Close(); err != nil {
1215 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1216 } else {
1217 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1218 }
1219 }
1220
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001221 logger.Debugw(ctx, "Dialing grpc", log.Fields{"device-id": dh.device.Id, "host-and-port": hostAndPort})
Abhay Kumard3f18512025-12-09 07:51:12 +00001222 grpc_prometheus.EnableClientHandlingTimeHistogram()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001223 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001224 dh.clientCon, err = grpc.DialContext(ctx, hostAndPort,
Girish Kumar93e91742020-07-27 16:43:19 +00001225 grpc.WithInsecure(),
1226 grpc.WithBlock(),
1227 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001228 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001229 grpc_prometheus.StreamClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001230 )),
1231 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001232 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001233 grpc_prometheus.UnaryClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001234 )))
1235
1236 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301237 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301238 "device-id": dh.device.Id,
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001239 "host-and-port": hostAndPort}, err)
Akash Sonif49299a2024-04-25 12:06:37 +05301240 }
1241
1242 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001243 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
Akash Sonif49299a2024-04-25 12:06:37 +05301244 DeviceId: dh.device.Id,
1245 OperStatus: voltha.OperStatus_RECONCILING,
1246 ConnStatus: voltha.ConnectStatus_REACHABLE,
1247 }); err != nil {
1248 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1249 }
1250 // 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
1251 // locally cached copy of the device struct.
1252 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1253 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1254 }
1255
Girish Gowdru0c588b22019-04-23 23:24:56 -04001256 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301257}
1258
1259// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301260func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001261 dh.Client = oop.NewOpenoltClient(dh.clientCon)
bseenivaa20d6c32026-01-11 21:51:19 +05301262 // decoupling it to avoid blocking state machine transition
1263 go dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001264 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301265}
1266
1267// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301268func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301269 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001270 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001271
1272 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001273 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301274 if err != nil || device == nil {
1275 /*TODO: needs to handle error scenarios */
1276 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1277 }
1278 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001279 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001280
1281 cloned := proto.Clone(device).(*voltha.Device)
1282 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1283 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1284 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001285
khenaidoodc2116e2021-10-19 17:33:19 -04001286 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001287 DeviceId: cloned.Id,
1288 OperStatus: cloned.OperStatus,
1289 ConnStatus: cloned.ConnectStatus,
1290 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301291 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 -04001292 }
1293
bseenivaa1622112025-12-11 18:24:02 +05301294 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Chaitrashree G S44124192019-08-07 20:21:36 -04001295 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
bseenivaa1622112025-12-11 18:24:02 +05301296 _, err = dh.Client.DisableOlt(subCtx, new(oop.Empty))
1297 cancel()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001298 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301299 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001300 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001301 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1302 // all the modules initialized and ready to handle incoming ONUs.
1303
Thomas Lee S985938d2020-05-04 11:40:41 +05301304 err = dh.initializeDeviceHandlerModules(ctx)
1305 if err != nil {
1306 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 -04001307 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001308
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001309 go startHeartbeatCheck(ctx, dh)
1310
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001311 return nil
1312 }
1313
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001314 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301315 logger.Error(ctx, "device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1316 cloned := proto.Clone(device).(*voltha.Device)
1317 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1318 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1319 dh.device = cloned
1320
1321 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
1322 DeviceId: cloned.Id,
1323 OperStatus: cloned.OperStatus,
1324 ConnStatus: cloned.ConnectStatus,
1325 }); err != nil {
1326 logger.Error(ctx, "device-state-update-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1327 }
1328 // decoupling it to avoid blocking state machine transition
1329 go dh.transitionMap.Handle(ctx, GrpcDisconnected)
1330 return nil
Girish Gowdru0c588b22019-04-23 23:24:56 -04001331 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301332
Neha Sharma96b7bf22020-06-15 10:37:32 +00001333 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001334
1335 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001336 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001337 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001338
1339 go startHeartbeatCheck(ctx, dh)
1340
cuilin20187b2a8c32019-03-26 19:52:28 -07001341 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301342}
1343
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001344func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001345 var err error
1346 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001347
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001348 if dh.flowMgr != nil {
1349 dh.StopAllFlowRoutines(ctx)
1350 }
1351
1352 dh.CloseKVClient(ctx)
1353
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001354 if err != nil {
1355 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1356 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001357 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1358 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301359 // If collector go routine is active, wait for it to stop
1360 dh.lockDevice.RLock()
1361 if dh.isCollectorActive {
1362 dh.lockDevice.RUnlock()
1363 dh.collectorWaitGroup.Wait()
1364 } else {
1365 dh.lockDevice.RUnlock()
1366 }
yasin saplid0566272021-12-21 09:10:30 +00001367 // +1 is for NNI
1368 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1369 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001370 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001371 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1372 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1373 // There is only one NNI manager since multiple NNI is not supported for now
1374 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001375 // Instantiate resource manager
1376 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 -07001377 return olterrors.ErrResourceManagerInstantiating
1378 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001379 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001380 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1381 // the KV store to manage mcast group data. Provide the first instance (0th index)
1382 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1383 return olterrors.ErrGroupManagerInstantiating
1384 }
yasin saplid0566272021-12-21 09:10:30 +00001385 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001386 // Instantiate flow manager
1387 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301388 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001389 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1390 } else {
1391 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001392 }
1393 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001394 /* TODO: Instantiate Alarm , stats , BW managers */
1395 /* Instantiating Event Manager to handle Alarms and KPIs */
1396 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1397
1398 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001399 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001400
1401 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001402}
1403
Neha Sharma96b7bf22020-06-15 10:37:32 +00001404func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001405 var err error
1406 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301407 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001408
bseenivaa1622112025-12-11 18:24:02 +05301409 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1410 deviceInfo, err = dh.Client.GetDeviceInfo(subCtx, new(oop.Empty))
1411 cancel()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001412
1413 if err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301414 return nil, olterrors.NewErrCommunication("get-device-info-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001415 }
1416 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001417 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001418 }
1419
Neha Sharma96b7bf22020-06-15 10:37:32 +00001420 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001421 dh.device.Root = true
1422 dh.device.Vendor = deviceInfo.Vendor
1423 dh.device.Model = deviceInfo.Model
1424 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1425 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1426 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1427
1428 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001429 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001430 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301431 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001432 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001433 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001434 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001435 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001436 dh.device.MacAddress = genmac
1437 } else {
1438 dh.device.MacAddress = deviceInfo.DeviceId
1439 }
1440
1441 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001442 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001443 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001444 }
1445
1446 return deviceInfo, nil
1447}
1448
Neha Sharma96b7bf22020-06-15 10:37:32 +00001449func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301450 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001451
1452 defer func() {
1453 dh.lockDevice.Lock()
1454 dh.isCollectorActive = false
1455 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301456 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001457 }()
1458
1459 dh.lockDevice.Lock()
1460 dh.isCollectorActive = true
1461 dh.lockDevice.Unlock()
1462
Naga Manjunath7615e552019-10-11 22:35:47 +05301463 for {
1464 select {
1465 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301466 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301467 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001468 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001469
khenaidoo106c61a2021-08-11 18:05:46 -04001470 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001471 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001472 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001473 continue
1474 }
khenaidoo106c61a2021-08-11 18:05:46 -04001475 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301476 // NNI Stats
1477 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001478 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301479 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001480 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001481 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001482 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301483 }
1484 // PON Stats
1485 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001486 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301487 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1488 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001489 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001490 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301491 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001492 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001493
yasin sapli9e4c5092022-02-01 13:52:33 +00001494 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001495 if len(onuGemInfoLst) > 0 {
1496 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001497 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001498 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301499 }
1500 }
1501 }
1502}
1503
Mahir Gunyela2e68702022-12-07 00:00:42 -08001504// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301505func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001506 var dhCtx context.Context
Girish Gowdru0c588b22019-04-23 23:24:56 -04001507 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001508 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001509 dhCtx, dh.transitionHandlerCancel = context.WithCancel(context.Background())
1510 dh.transitionMap.Handle(dhCtx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301511
1512 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001513 cgClient, err := dh.coreClient.GetCoreServiceClient()
1514 if err != nil {
1515 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1516 return
1517 }
1518
1519 // Now, set the initial PM configuration for that device
1520 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001521 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301522 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301523}
1524
Mahir Gunyela2e68702022-12-07 00:00:42 -08001525// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001526func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1527 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001528 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301529 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001530 HwDesc: "open_pon",
1531 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001532 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001533 },
1534 SwitchFeatures: &of.OfpSwitchFeatures{
1535 NBuffers: 256,
1536 NTables: 2,
1537 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1538 of.OfpCapabilities_OFPC_TABLE_STATS |
1539 of.OfpCapabilities_OFPC_PORT_STATS |
1540 of.OfpCapabilities_OFPC_GROUP_STATS),
1541 },
1542 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301543}
1544
khenaidoo106c61a2021-08-11 18:05:46 -04001545// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001546func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001547 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001548 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001549 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001550 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001551 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1552 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()
1553 }
khenaidoo106c61a2021-08-11 18:05:46 -04001554 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001555}
1556
Neha Sharma96b7bf22020-06-15 10:37:32 +00001557func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001558 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 -07001559 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001560 var deviceID string
1561 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001562 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001563
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001564 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001565 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001566 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 -07001567 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1568 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001569
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001570 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301571
1572 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001573 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 -07001574 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001575
khenaidoodc2116e2021-10-19 17:33:19 -04001576 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001577 ParentId: dh.device.Id,
1578 OnuId: omciInd.OnuId,
1579 ParentPortNo: ponPort,
1580 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001581 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301582 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001583 "intf-id": omciInd.IntfId,
1584 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001585 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001586 deviceType = onuDevice.Type
1587 deviceID = onuDevice.Id
1588 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001589 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301590 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001591 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001592 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301593 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 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 +05301595 deviceType = onuInCache.(*OnuDevice).deviceType
1596 deviceID = onuInCache.(*OnuDevice).deviceID
1597 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001598 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001599 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001600
khenaidoodc2116e2021-10-19 17:33:19 -04001601 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001602 ParentDeviceId: proxyDeviceID,
1603 ChildDeviceId: deviceID,
1604 Message: omciInd.Pkt,
1605 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301606 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001607 "source": dh.openOLT.config.AdapterEndpoint,
1608 "device-type": deviceType,
1609 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001611 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001612 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001613 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301614}
1615
khenaidoo106c61a2021-08-11 18:05:46 -04001616// //ProcessInterAdapterMessage sends the proxied messages to the target device
1617// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1618// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001619// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001620// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001621// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001622// return dh.handleInterAdapterOmciMsg(ctx, msg)
1623// }
1624// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1625// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001626
kesavandb9f54fd2021-11-25 20:08:04 +05301627// ProxyOmciRequests sends the proxied OMCI message to the target device
1628func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301629 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1630 return status.Error(codes.Unavailable, "OLT unreachable")
1631 }
kesavandb9f54fd2021-11-25 20:08:04 +05301632 if omciMsgs.GetProxyAddress() == nil {
1633 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1634 if err != nil {
1635 return olterrors.NewErrNotFound("onu", log.Fields{
1636 "parent-device-id": dh.device.Id,
1637 "child-device-id": omciMsgs.ChildDeviceId}, err)
1638 }
1639 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1640 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1641 return olterrors.NewErrCommunication("send-failed", log.Fields{
1642 "parent-device-id": dh.device.Id,
1643 "child-device-id": omciMsgs.ChildDeviceId}, err)
1644 }
1645 } else {
1646 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1647 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1648 return olterrors.NewErrCommunication("send-failed", log.Fields{
1649 "parent-device-id": dh.device.Id,
1650 "child-device-id": omciMsgs.ChildDeviceId}, err)
1651 }
1652 }
1653 return nil
1654}
1655
1656func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1657 var intfID uint32
1658 var onuID uint32
1659 var connectStatus common.ConnectStatus_Types
1660 if onuDevice != nil {
1661 intfID = onuDevice.ProxyAddress.GetChannelId()
1662 onuID = onuDevice.ProxyAddress.GetOnuId()
1663 connectStatus = onuDevice.ConnectStatus
1664 } else {
1665 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1666 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1667 connectStatus = omciMsgs.GetConnectStatus()
1668 }
1669 if connectStatus != voltha.ConnectStatus_REACHABLE {
1670 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1671
1672 return olterrors.NewErrCommunication("unreachable", log.Fields{
1673 "intf-id": intfID,
1674 "onu-id": onuID}, nil)
1675 }
1676
1677 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1678 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1679
1680 onuSecOmciMsgList := omciMsgs.GetMessages()
1681
1682 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301683 var omciMessage *oop.OmciMsg
1684 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1685 hex.Encode(hexPkt, onuSecOmciMsg)
1686 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1687
1688 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1689 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1690 //https://jira.opencord.org/browse/VOL-4604
1691 transid := extractOmciTransactionID(onuSecOmciMsg)
1692 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1693 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1694
bseenivaa1622112025-12-11 18:24:02 +05301695 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1696 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1697 cancel()
kesavandb9f54fd2021-11-25 20:08:04 +05301698 if err != nil {
1699 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1700 "intf-id": intfID,
1701 "onu-id": onuID,
1702 "message": omciMessage}, err)
1703 }
1704 }
1705 return nil
1706}
1707
khenaidoo106c61a2021-08-11 18:05:46 -04001708// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001709func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001710 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 -07001711
Akash Reddy Kankanala7b4d57e2026-01-26 23:18:18 +05301712 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) || DeviceState(dh.device.OperStatus) != DeviceState(voltha.OperStatus_ACTIVE) {
1713 return status.Error(codes.Unavailable, "OLT-is-unreachable-or-not-active")
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301714 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001715 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001716 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001717 if err != nil {
1718 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001719 "parent-device-id": dh.device.Id,
1720 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001721 }
khenaidoo106c61a2021-08-11 18:05:46 -04001722 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1723 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001724 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001725 "parent-device-id": dh.device.Id,
1726 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001727 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001728 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001729 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1730 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001731 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001732 "parent-device-id": dh.device.Id,
1733 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001734 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001735 }
1736 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301737}
1738
khenaidoodc2116e2021-10-19 17:33:19 -04001739func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001740 var intfID uint32
1741 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001742 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001743 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001744 intfID = onuDevice.ProxyAddress.GetChannelId()
1745 onuID = onuDevice.ProxyAddress.GetOnuId()
1746 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001747 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001748 intfID = omciMsg.GetProxyAddress().GetChannelId()
1749 onuID = omciMsg.GetProxyAddress().GetOnuId()
1750 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001751 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001752 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001753 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 -08001754
Thomas Lee S94109f12020-03-03 16:39:29 +05301755 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001756 "intf-id": intfID,
1757 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001758 }
1759
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001760 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1761 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301762 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001763 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001764 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1765 hex.Encode(hexPkt, omciMsg.Message)
1766 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1767
1768 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1769 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1770 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001771 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001772 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001773
bseenivaa1622112025-12-11 18:24:02 +05301774 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1775 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1776 cancel()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001777 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301778 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001779 "intf-id": intfID,
1780 "onu-id": onuID,
1781 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001782 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001783 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001784}
1785
David K. Bainbridge794735f2020-02-11 21:01:37 -08001786func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301787 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 +00001788 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001789 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001790 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001791 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301792 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
bseenivaa1622112025-12-11 18:24:02 +05301793 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1794 defer cancel()
1795 if _, err := dh.Client.ActivateOnu(subCtx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001796 st, _ := status.FromError(err)
1797 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001798 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 -04001799 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301800 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001801 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001802 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001804 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001805 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001806}
1807
Mahir Gunyela2e68702022-12-07 00:00:42 -08001808// getChildDevice function can be used in general to get child device, if not found in cache the function will
1809// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301810func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1811 var InCacheOnuDev *OnuDevice
1812 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1813 if onuInCache.(*OnuDevice).serialNumber == sn {
1814 InCacheOnuDev = onuInCache.(*OnuDevice)
1815 return false
1816 }
1817 return true
1818 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301819 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301820 if InCacheOnuDev != nil {
1821 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1822 return InCacheOnuDev
1823 }
1824 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1825 ParentId: dh.device.Id,
1826 SerialNumber: sn,
1827 ParentPortNo: parentPortNo,
1828 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301829 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301830 if onuDevice == nil {
1831 return nil
1832 }
1833 onuID := onuDevice.ProxyAddress.OnuId
1834 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1835 onuKey := dh.formOnuKey(intfID, onuID)
1836
1837 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1838 dh.onus.Store(onuKey, onuDev)
1839 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1840 return onuDev
1841}
1842
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301843// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1844// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301845func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001846 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301847 // 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 +05301848 // 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 +05301849 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1850 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1851 ParentId: dh.device.Id,
1852 SerialNumber: sn,
1853 ParentPortNo: parentPortNo,
1854 })
1855 if onuDevice != nil {
1856 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1857 return true, nil
1858 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05301859 logger.Debugw(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301860
1861 return false, nil
1862 } else {
1863 tpInstExists := false
1864 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301865 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1866 if onuDev != nil {
1867 var onuGemInfo *rsrcMgr.OnuGemInfo
1868 var err error
1869 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1870 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1871 return false, err
1872 }
1873 if onuGemInfo != nil {
1874 for _, uni := range onuGemInfo.UniPorts {
1875 uniID := plt.UniIDFromPortNum(uni)
1876 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1877 if len(tpIDs) != 0 {
1878 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1879 tpInstExists = true
1880 break
1881 }
1882 }
1883 }
1884 }
1885 return tpInstExists, nil
1886 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301887}
1888
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001889// processDiscONULOSClear clears the LOS Alarm if it's needed
1890func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301891 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001892 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301893
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001894 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1895 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1896 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1897 OnuLosRaise event sent for it */
1898 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1899 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1900 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1901 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1902 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1903 "currentIntfId": onuDiscInd.GetIntfId()})
1904 // TODO:: Should we need to ignore raising OnuLosClear event
1905 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301906 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001907 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1908 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1909 alarmInd.LosStatus = statusCheckOff
1910 go func() {
1911 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1912 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1913 }
1914 }()
1915 // stop iterating
1916 return false
1917 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301918 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001919 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301920}
1921
bseeniva43b5a912025-06-05 12:48:15 +05301922func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1923 if err != nil || tpInstExists {
1924 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1925 } else {
1926 // once the function completes set the value to false so that
1927 // we know the processing has inProcess.
1928 // Note that this is done after checking if we are already processing
1929 // to avoid changing the value from a different thread
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05301930 logger.Debugw(ctx, "onu-processing-completed", log.Fields{"sn": sn})
bseeniva43b5a912025-06-05 12:48:15 +05301931 dh.discOnus.Store(sn, false)
1932 }
1933}
1934
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301935func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301936 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301937 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301938
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301939 channelID := onuDiscInd.GetIntfId()
1940 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1941
1942 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301943 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301944 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301945 }()
1946
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301947 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1948
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301949 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1950 if !dh.cfg.ForceOnuDiscIndProcessing {
1951 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1952 if error != nil {
1953 return error
1954 }
1955 if tpInstExists {
1956 // ignore the discovery if tpinstance is present.
1957 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1958 return nil
1959 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001960 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001961 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1962
1963 // if the ONU existed, handle the LOS Alarm
1964 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001965 if inProcess.(bool) {
1966 // if we're currently processing the ONU on a different thread, do nothing
1967 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1968 return nil
1969 }
1970 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1971 // then continue processing it
1972 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1973
1974 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001975 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301976 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001977 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001978
1979 // check the ONU is already know to the OLT
1980 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301981 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001982 ParentId: dh.device.Id,
1983 SerialNumber: sn,
1984 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001985
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301986 if error != nil {
1987 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1988 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001989 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 -08001990 switch e.Code() {
1991 case codes.Internal:
1992 // this probably means NOT FOUND, so just create a new device
1993 onuDevice = nil
1994 case codes.DeadlineExceeded:
1995 // if the call times out, cleanup and exit
1996 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301997 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1998 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001999 }
2000 }
2001 }
2002
2003 if onuDevice == nil {
2004 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00002005 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002006 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04002007 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302008 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002009 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002010
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302011 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002012 // if we can't create an ID in resource manager,
2013 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08002014 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302015
2016 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002017 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302018 "serial-number": sn}, error)
2019 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002020 }
2021
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302022 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04002023 ParentId: dh.device.Id,
2024 ParentPortNo: parentPortNo,
2025 ChannelId: channelID,
2026 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
2027 SerialNumber: sn,
2028 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302029 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002030 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00002031 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 +05302032
2033 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002034 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302035 "serial-number": sn}, error)
2036 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002037 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302038 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 +05302039 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2040 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2041 "onu-id": onuID,
2042 "device-id": dh.device.Id,
2043 "serial-number": sn}, error)
2044 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002045 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302046 logger.Debugw(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302047 log.Fields{"onuDevice": onuDevice,
2048 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002049 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302050 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002051 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002052
khenaidoo106c61a2021-08-11 18:05:46 -04002053 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2054 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302055 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002056 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302057 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302058 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2059 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002060 }
2061
Matteo Scandolo945e4012019-12-12 14:16:11 -08002062 // we can now use the existing ONU Id
2063 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302064 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002065 //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 +00002066 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002067 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302068 "intfId": onuDiscInd.GetIntfId(),
2069 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002070 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002071
khenaidoo106c61a2021-08-11 18:05:46 -04002072 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302073 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002074 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302075 log.Fields{"onu": onuDev,
2076 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002077
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302078 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002079 DeviceId: onuDevice.Id,
2080 ParentDeviceId: dh.device.Id,
2081 OperStatus: common.OperStatus_DISCOVERED,
2082 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302083 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302084 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002085 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302086 "serial-number": sn}, error)
2087 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002088 }
khenaidoo106c61a2021-08-11 18:05:46 -04002089
Neha Sharma96b7bf22020-06-15 10:37:32 +00002090 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302091 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302092 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002093 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302094 "serial-number": sn}, error)
2095 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002096 }
2097 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002098}
2099
Mahir Gunyelb0046752021-02-26 13:51:05 -08002100func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002101 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002102 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002103 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002104 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002105 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302106 log.Fields{"onuId": onuInd.OnuId,
2107 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302108 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002109 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002110 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002111 errFields := log.Fields{"device-id": dh.device.Id}
2112
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302113 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302114 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002115 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002116 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002117 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002118 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302119 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002120 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002121 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002122 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002123 errFields["onu-id"] = onuInd.OnuId
2124 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002125 }
khenaidoodc2116e2021-10-19 17:33:19 -04002126 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002127 ParentId: dh.device.Id,
2128 SerialNumber: serialNumber,
2129 OnuId: onuInd.OnuId,
2130 ParentPortNo: ponPort,
2131 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002132 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002133
David K. Bainbridge794735f2020-02-11 21:01:37 -08002134 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002135 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002136 }
2137
David K. Bainbridge794735f2020-02-11 21:01:37 -08002138 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002139 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002140 "previousIntfId": onuDevice.ParentPortNo,
2141 "currentIntfId": ponPort})
2142 }
2143
2144 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302146 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2147 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302148 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002149 }
2150 if !foundInCache {
2151 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002152 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 -08002153 }
kesavand7cf3a052020-08-28 12:49:18 +05302154 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002155 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002156 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302157 }
2158 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002159 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002160 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002161 }
2162 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002163}
2164
Neha Sharma96b7bf22020-06-15 10:37:32 +00002165func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002166 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 -07002167 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2168 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2169 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2170 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002171 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002172 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2173 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002175 onuInd.OperState = "down"
2176 }
2177 }
2178
David K. Bainbridge794735f2020-02-11 21:01:37 -08002179 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002180 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 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 -04002182
khenaidoodc2116e2021-10-19 17:33:19 -04002183 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002184 DeviceId: onuDevice.Id,
2185 OnuIndication: onuInd,
2186 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002187 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302188 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002189 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002190 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002191 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002192 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002193 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002194 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002195 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002196 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002197 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002198}
2199
cuilin20187b2a8c32019-03-26 19:52:28 -07002200func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2201 if serialNum != nil {
2202 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002203 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002204 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002205}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002206func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2207 decodedStr, err := hex.DecodeString(serialNum[4:])
2208 if err != nil {
2209 return nil, err
2210 }
2211 return &oop.SerialNumber{
2212 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002213 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002214 }, nil
2215}
cuilin20187b2a8c32019-03-26 19:52:28 -07002216
2217func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002218 if len(vendorSpecific) > 3 {
2219 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2220 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2221 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2222 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2223 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2224 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2225 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2226 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2227 return tmp
2228 }
2229 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002230}
2231
Mahir Gunyela2e68702022-12-07 00:00:42 -08002232// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002233func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302234 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002235}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002236
Mahir Gunyela2e68702022-12-07 00:00:42 -08002237// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002238func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2239 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302240 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002241 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302242 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002243
khenaidoodc2116e2021-10-19 17:33:19 -04002244 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002245 ParentId: dh.device.Id,
2246 OnuId: onuID,
2247 ParentPortNo: parentPort,
2248 })
2249
Girish Gowdru0c588b22019-04-23 23:24:56 -04002250 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002251 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002252 "intf-id": parentPort,
2253 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002254 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255 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 -08002256 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302257}
2258
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002259// SendPacketInToCore sends packet-in to core
2260// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2261// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002262func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002263 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002265 "port": logicalPort,
2266 "packet": hex.EncodeToString(packetPayload),
2267 "device-id": dh.device.Id,
2268 })
2269 }
khenaidoo106c61a2021-08-11 18:05:46 -04002270
khenaidoodc2116e2021-10-19 17:33:19 -04002271 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002272 DeviceId: dh.device.Id,
2273 Port: logicalPort,
2274 Packet: packetPayload,
2275 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302276 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002277 "source": "adapter",
2278 "destination": "core",
2279 "device-id": dh.device.Id,
2280 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002281 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002282 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002283 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002284 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002285 "packet": hex.EncodeToString(packetPayload),
2286 "device-id": dh.device.Id,
2287 })
2288 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002289 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002290}
2291
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002292// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002293func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002295
2296 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2297 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002298 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002299 }
2300
Kent Hagermane6ff1012020-07-14 15:07:53 -04002301 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002302 metrics := dh.metrics.GetSubscriberMetrics()
2303 for _, m := range pmConfigs.Metrics {
2304 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002305 }
2306 }
2307}
2308
khenaidoodc2116e2021-10-19 17:33:19 -04002309func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002310 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002311 var errorsList []error
2312
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002313 if dh.getDeviceDeletionInProgressFlag() {
2314 // The device itself is going to be reset as part of deletion. So nothing to be done.
2315 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2316 return nil
2317 }
2318
Girish Gowdru0c588b22019-04-23 23:24:56 -04002319 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002320 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302321 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002322
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302324 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002325 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302326 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002327 if flow_utils.HasGroup(flow) {
2328 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2329 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002330 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2331 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2332 } else {
2333 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2334 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002335 }
Girish Gowdracefae192020-03-19 18:14:10 -07002336 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002337 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302338 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002339 logger.Warnw(ctx, "flow-to-remove-not-found",
2340 log.Fields{
2341 "ponIf": intfID,
2342 "flowToRemove": flow,
2343 "error": err,
2344 })
2345 } else {
2346 errorsList = append(errorsList, err)
2347 }
Girish Gowdracefae192020-03-19 18:14:10 -07002348 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002349 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302350
2351 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302352 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002353 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302354 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002355 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302356 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002357 if flow_utils.HasGroup(flow) {
2358 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2359 } else {
yasin saplid0566272021-12-21 09:10:30 +00002360 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002361 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2362 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2363 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2364 } else {
yasin saplid0566272021-12-21 09:10:30 +00002365 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002366 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002367 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002368 if err != nil {
2369 errorsList = append(errorsList, err)
2370 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302371 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002372 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002373
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002374 return errorsList
2375}
2376
2377func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2378 var err error
2379 var errorsList []error
2380
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002381 if dh.getDeviceDeletionInProgressFlag() {
2382 // The device itself is going to be reset as part of deletion. So nothing to be done.
2383 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2384 return nil
2385 }
2386
Girish Gowdracefae192020-03-19 18:14:10 -07002387 // 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 +00002388 if groups != nil {
2389 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002390 // err = dh.groupMgr.AddGroup(ctx, group)
2391 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002392 if err != nil {
2393 errorsList = append(errorsList, err)
2394 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002395 }
2396 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002397 // err = dh.groupMgr.ModifyGroup(ctx, group)
2398 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002399 if err != nil {
2400 errorsList = append(errorsList, err)
2401 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002402 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002403 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002404 // err = dh.groupMgr.DeleteGroup(ctx, group)
2405 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002406 if err != nil {
2407 errorsList = append(errorsList, err)
2408 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002409 }
2410 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002411
2412 return errorsList
2413}
2414
Mahir Gunyela2e68702022-12-07 00:00:42 -08002415// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002416func (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 -07002417 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002418
2419 if dh.getDeviceDeletionInProgressFlag() {
2420 // The device itself is going to be reset as part of deletion. So nothing to be done.
2421 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2422 return nil
2423 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302424 if dh.transitionMap.currentDeviceState != deviceStateUp {
2425 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2426 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2427 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002428 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2429 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2430 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002431 if len(errorsList) > 0 {
2432 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2433 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002434 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002435 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302436}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002437
Mahir Gunyela2e68702022-12-07 00:00:42 -08002438// DisableDevice disables the given device
2439// It marks the following for the given device:
2440// Device-Handler Admin-State : down
2441// Device Port-State: UNKNOWN
2442// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002444 /* On device disable ,admin state update has to be done prior sending request to agent since
2445 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002446 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302447 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2448 if _, err := dh.Client.DisableOlt(subCtx, new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002449 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302450 cancel()
Girish Kumarf26e4882020-03-05 06:49:10 +00002451 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002452 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002453 }
bseenivaa1622112025-12-11 18:24:02 +05302454 cancel()
Chaitrashree G S44124192019-08-07 20:21:36 -04002455 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002456 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002457 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002458 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302459
2460 dh.discOnus = sync.Map{}
2461 dh.onus = sync.Map{}
2462
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002463 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302464 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002465 if dh.isCollectorActive {
2466 dh.stopCollector <- true
2467 }
2468 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302469
Neha Sharma96b7bf22020-06-15 10:37:32 +00002470 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002471 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302472 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302473 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002474
kdarapu1afeceb2020-02-12 01:38:09 -05002475 // 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 -04002476 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002477 DeviceId: cloned.Id,
2478 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2479 OperStatus: voltha.OperStatus_UNKNOWN,
2480 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002481 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002482 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002484 return nil
2485}
2486
Neha Sharma96b7bf22020-06-15 10:37:32 +00002487func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002488 // Update onu state as unreachable in onu adapter
2489 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302490 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002491
Akash Kankanala041a2122024-10-16 15:49:22 +05302492 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002493 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002494 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002495 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 -04002496 }
2497 if onuDevices != nil {
2498 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002499 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002500 DeviceId: onuDevice.Id,
2501 OnuIndication: &onuInd,
2502 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002503 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002504 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002505 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002506 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002507 }
2508 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002509}
2510
Mahir Gunyela2e68702022-12-07 00:00:42 -08002511// ReenableDevice re-enables the olt device after disable
2512// It marks the following for the given device:
2513// Device-Handler Admin-State : up
2514// Device Port-State: ACTIVE
2515// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002516func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302517 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302518 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2519 if _, err := dh.Client.ReenableOlt(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302520 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302521 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302522 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2523 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302524 }
bseenivaa1622112025-12-11 18:24:02 +05302525 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302526 } else {
2527 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 +05302528 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002529 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002530
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002531 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002532 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002533 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002534 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002535 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2536 } else {
2537 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2538 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2539 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002540 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002541 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302542 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002543 device.OperStatus = voltha.OperStatus_ACTIVE
2544 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302545 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002546 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002547 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002548 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002549
khenaidoodc2116e2021-10-19 17:33:19 -04002550 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002551 DeviceId: device.Id,
2552 OperStatus: device.OperStatus,
2553 ConnStatus: device.ConnectStatus,
2554 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302555 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002556 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002557 "connect-status": device.ConnectStatus,
2558 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002559 }
kesavand39e0aa32020-01-28 20:58:50 -05002560
Neha Sharma96b7bf22020-06-15 10:37:32 +00002561 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002562
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002563 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002564}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002565
npujarec5762e2020-01-01 14:08:48 +05302566func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002567 var uniID uint32
2568 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002569 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302570 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002571 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002572 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002573 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002574 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2575 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2576 } else {
2577 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2578 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002579 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002580 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002581 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002582 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002583 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002584 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002585 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002586 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002587 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002588 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002589 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002590 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002591 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002592 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002593 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002594 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302595 }
yasin saplibddc2d72022-02-08 13:10:17 +00002596 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2597 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002598 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002599 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302600 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002601 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002602 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002603 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 -03002604 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002605 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002606 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002607 if len(errs) > 0 {
2608 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2609 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2610 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002611 return nil
2612}
2613
Devmalya Paul495b94a2019-08-27 19:42:00 -04002614// 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 +05302615func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002616 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002617 /* Clear the KV store data associated with the all the UNI ports
2618 This clears up flow data and also resource map data for various
2619 other pon resources like alloc_id and gemport_id
2620 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002621
Abhay Kumarb87ac882025-10-30 09:55:07 +00002622 if dh.getDeviceDeletionInProgressFlag() {
2623 logger.Errorw(ctx, "cannot complete operation as device deletion is in progress", log.Fields{"device-id": dh.device.Id})
2624 return olterrors.NewErrAdapter(fmt.Errorf("cannot complete operation as device deletion is in progress").Error(), log.Fields{"device-id": dh.device.Id}, nil)
2625 }
2626
Girish Gowdra950326e2021-11-05 12:43:24 -07002627 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002628 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002629
Himani Chawla49a5d562020-11-25 11:53:44 +05302630 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002631 // Stop the Stats collector
2632 if dh.isCollectorActive {
2633 dh.stopCollector <- true
2634 }
2635 // stop the heartbeat check routine
2636 if dh.isHeartbeatCheckActive {
2637 dh.stopHeartbeatCheck <- true
2638 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302639 // Stop the read indication only if it the routine is active
2640 if dh.isReadIndicationRoutineActive {
2641 dh.stopIndications <- true
2642 }
2643 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302644
2645 err := dh.cleanupDeviceResources(ctx)
2646 if err != nil {
2647 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
balaji.nagarajan2e572c42026-01-27 15:09:39 +05302648 dh.setDeviceDeletionInProgressFlag(false)
2649 return status.Error(codes.Internal, olterrors.NewErrAdapter("could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id}, err).Error())
Akash Soni5c76e272024-01-15 04:09:24 +05302650 } else {
2651 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2652 }
2653
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002654 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302655 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002656 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302657 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2658 if _, err = dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002659 go func() {
2660 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302661 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2662 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002663 }
2664 }()
2665 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002666 }
bseenivaa1622112025-12-11 18:24:02 +05302667 cancel()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002668 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002669 // There is no need to update the core about operation status and connection status of the OLT.
2670 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2671 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2672 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002673
khenaidoo7eb2d672021-10-22 19:08:50 -04002674 // Stop the adapter grpc clients for that parent device
2675 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002676 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002677}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002678
2679// StopAllFlowRoutines stops all flow routines
2680func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2681 var wg sync.WaitGroup
2682 wg.Add(1) // for the mcast routine below to finish
2683 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2684 for _, flMgr := range dh.flowMgr {
2685 if flMgr != nil {
2686 wg.Add(1) // for the flow handler routine below to finish
2687 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2688 }
2689 }
2690 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2691 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2692 } else {
2693 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2694 }
2695}
2696
Gustavo Silva41af9122022-10-11 11:05:13 -03002697func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2698 var errs []error
Abhay Kumarb87ac882025-10-30 09:55:07 +00002699 if dh.resourceMgr != nil && dh.totalPonPorts > 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302700 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002701 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002702 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002703 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002704 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002705 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2706 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302707 }
2708 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002709 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2710 errs = append(errs, err)
2711 }
2712 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2713 errs = append(errs, err)
2714 }
2715 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2716 errs = append(errs, err)
2717 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002718 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002719 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002720 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002721 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002722 }
2723 // Clean up NNI manager's data
2724 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2725 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002726 }
A R Karthick1f85b802019-10-11 05:06:05 +00002727
balaji.nagarajan2e572c42026-01-27 15:09:39 +05302728 if len(errs) == 0 {
2729 // Take one final sweep at cleaning up KV store for the OLT device
2730 // Clean everything at <base-path-prefix>/openolt/<device-id>
2731 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2732 errs = append(errs, err)
2733 }
2734 logger.Debugw(ctx, "lockDevice for KVStore close client", log.Fields{"deviceID": dh.device.Id})
2735 dh.CloseKVClient(ctx)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002736 }
2737
Devmalya Paul495b94a2019-08-27 19:42:00 -04002738 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302739 dh.onus.Range(func(key interface{}, value interface{}) bool {
2740 dh.onus.Delete(key)
2741 return true
2742 })
2743
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002744 /*Delete discovered ONU map for the device*/
2745 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2746 dh.discOnus.Delete(key)
2747 return true
2748 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002749 if len(errs) > 0 {
2750 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2751 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2752 }
2753 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002754}
2755
Mahir Gunyela2e68702022-12-07 00:00:42 -08002756// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002757func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302758 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302759 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2760 defer cancel()
2761 if _, err := dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302762 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2763 }
2764 } else {
2765 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 -04002766 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302767
Neha Sharma96b7bf22020-06-15 10:37:32 +00002768 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002769 return nil
2770}
2771
David K. Bainbridge794735f2020-02-11 21:01:37 -08002772func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002773 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002774 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002775 "packet-indication": *packetIn,
2776 "device-id": dh.device.Id,
2777 "packet": hex.EncodeToString(packetIn.Pkt),
2778 })
2779 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002780 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2781 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2782 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002783 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002784 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002785 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002786 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002787 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002788 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002789 "logical-port-num": logicalPortNum,
2790 "device-id": dh.device.Id,
2791 "packet": hex.EncodeToString(packetIn.Pkt),
2792 })
2793 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002794
khenaidoodc2116e2021-10-19 17:33:19 -04002795 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002796 DeviceId: dh.device.Id,
2797 Port: logicalPortNum,
2798 Packet: packetIn.Pkt,
2799 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302800 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002801 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302802 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002803 "device-id": dh.device.Id,
2804 "packet": hex.EncodeToString(packetIn.Pkt),
2805 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002806 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002807
Matteo Scandolo92186242020-06-12 10:54:18 -07002808 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002809 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002810 "packet": hex.EncodeToString(packetIn.Pkt),
2811 "device-id": dh.device.Id,
2812 })
2813 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002814 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002815}
2816
Mahir Gunyela2e68702022-12-07 00:00:42 -08002817// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2818func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2819 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2820 if err != nil {
2821 return olterrors.NewErrInvalidValue(log.Fields{
2822 "egress-nni-port": egressPortNo,
2823 "device-id": dh.device.Id,
2824 }, err)
2825 }
2826 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2827
2828 if logger.V(log.DebugLevel) {
2829 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2830 "uplink-pkt": uplinkPkt,
2831 "packet": hex.EncodeToString(packet.Data),
2832 "device-id": dh.device.Id,
2833 })
2834 }
2835
bseenivaa1622112025-12-11 18:24:02 +05302836 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2837 defer cancel()
2838 if _, err := dh.Client.UplinkPacketOut(subCtx, &uplinkPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002839 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2840 "packet": hex.EncodeToString(packet.Data),
2841 "device-id": dh.device.Id,
2842 }, err)
2843 }
2844 return nil
2845}
2846
2847// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2848func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2849 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2850 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2851 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2852 // Do not packet-out lldp packets on uni port.
2853 // ONOS has no clue about uni/nni ports, it just packets out on all
2854 // available ports on the Logical Switch. It should not be interested
2855 // in the UNI links.
2856 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2857 "device-id": dh.device.Id,
2858 })
2859 return nil
2860 }
2861 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2862 if innerEthType == 0x8100 {
2863 // q-in-q 802.1ad or 802.1q double tagged packet.
2864 // slice out the outer tag.
2865 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2866 if logger.V(log.DebugLevel) {
2867 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2868 "packet-data": hex.EncodeToString(packet.Data),
2869 "device-id": dh.device.Id,
2870 })
2871 }
2872 }
2873 }
2874 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2875 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2876 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2877 var gemPortID uint32
2878 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2879 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2880 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2881 }
2882 if err != nil {
2883 // In this case the openolt agent will receive the gemPortID as 0.
2884 // The agent tries to retrieve the gemPortID in this case.
2885 // This may not always succeed at the agent and packetOut may fail.
2886 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2887 "intf-id": intfID,
2888 "onu-id": onuID,
2889 "uni-id": uniID,
2890 "packet": hex.EncodeToString(packet.Data),
2891 "device-id": dh.device.Id,
2892 "error": err,
2893 })
2894 }
2895
2896 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2897 if logger.V(log.DebugLevel) {
2898 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2899 "egress-port-no": egressPortNo,
2900 "intf-id": intfID,
2901 "onu-id": onuID,
2902 "uni-id": uniID,
2903 "gem-port-id": gemPortID,
2904 "packet": hex.EncodeToString(packet.Data),
2905 "device-id": dh.device.Id,
2906 })
2907 }
2908
bseenivaa1622112025-12-11 18:24:02 +05302909 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2910 defer cancel()
2911 if _, err := dh.Client.OnuPacketOut(subCtx, &onuPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002912 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2913 "source": "adapter",
2914 "destination": "onu",
2915 "egress-port-number": egressPortNo,
2916 "intf-id": intfID,
2917 "oni-id": onuID,
2918 "uni-id": uniID,
2919 "gem-port-id": gemPortID,
2920 "packet": hex.EncodeToString(packet.Data),
2921 "device-id": dh.device.Id,
2922 }, err)
2923 }
2924 return nil
2925}
2926
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002927// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002928func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002929 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002930 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002931 "device-id": dh.device.Id,
2932 "egress-port-no": egressPortNo,
2933 "pkt-length": len(packet.Data),
2934 "packet": hex.EncodeToString(packet.Data),
2935 })
2936 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002937
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002938 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002939 var err error
mgouda86543582025-10-29 20:58:16 +05302940 switch egressPortType {
2941 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002942 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302943 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002944 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302945 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002946 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302947 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002948 "egressPortType": egressPortType,
2949 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302950 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002951 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002952 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002953 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002954}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002955
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002956func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2957 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002958}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302959
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002960func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002961 defer func() {
2962 dh.lockDevice.Lock()
2963 dh.isHeartbeatCheckActive = false
2964 dh.lockDevice.Unlock()
2965 }()
2966
2967 dh.lockDevice.Lock()
2968 dh.isHeartbeatCheckActive = true
2969 dh.lockDevice.Unlock()
2970
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302971 // start the heartbeat check towards the OLT.
2972 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302973 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302974
2975 for {
2976 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2977 select {
2978 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002979 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002980 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002981 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302982 if timerCheck == nil {
2983 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002984 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302985 }
2986 } else {
2987 if timerCheck != nil {
2988 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002989 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302990 }
2991 timerCheck = nil
2992 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302993 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2994 if dh.heartbeatSignature == 0 {
2995 // First time the signature will be 0, update the signture to DB when not found.
2996 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2997 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2998 }
2999 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
3000
3001 dh.lockDevice.RLock()
3002 // Stop the read indication only if it the routine is active
3003 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3004 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3005 // on next execution of the readIndication routine.
3006 if !dh.isReadIndicationRoutineActive {
3007 // Start reading indications
3008 go func() {
3009 if err = dh.readIndications(ctx); err != nil {
3010 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3011 }
3012 }()
3013 }
3014 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303015 } else {
3016 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
balaji.nagarajan2e572c42026-01-27 15:09:39 +05303017 dh.updateStateRebooted(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303018 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
3019 dh.heartbeatSignature = heartBeat.HeartbeatSignature
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303020 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303021 }
3022 cancel()
3023 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003024 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303025 return
3026 }
3027 }
3028}
3029
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003030func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04003031 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003032 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07003033 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3034 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3035 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3036 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3037 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003038 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07003039 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3040 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003041 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303042
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303043 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003044 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003045 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04003046 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04003047 DeviceId: dh.device.Id,
3048 OperStatus: voltha.OperStatus_UNKNOWN,
3049 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
3050 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003051 _ = 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 -04003052 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303053 /*
3054 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
3055 DeviceId: dh.device.Id,
3056 PortTypeFilter: 0,
3057 OperStatus: voltha.OperStatus_UNKNOWN,
3058 }); err != nil {
3059 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3060 }
3061 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003062
Akash Kankanala041a2122024-10-16 15:49:22 +05303063 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003064 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003065 cloned := proto.Clone(device).(*voltha.Device)
3066 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3067 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3068 dh.device = cloned // update local copy of the device
3069 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003070
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003071 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003072 // Stop the Stats collector
3073 if dh.isCollectorActive {
3074 dh.stopCollector <- true
3075 }
3076 // stop the heartbeat check routine
3077 if dh.isHeartbeatCheckActive {
3078 dh.stopHeartbeatCheck <- true
3079 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003080 // Stop the read indication only if it the routine is active
3081 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3082 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3083 // on next execution of the readIndication routine.
3084 if dh.isReadIndicationRoutineActive {
3085 dh.stopIndications <- true
3086 }
3087 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003088 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303089 }
3090}
kesavand39e0aa32020-01-28 20:58:50 -05003091
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303092func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3093 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3094 if err != nil || device == nil {
3095 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3096 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3097 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3098 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3099 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3100 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3101 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3102 return
3103 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303104 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003105 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303106
3107 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3108 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303109 // First, stop the read indication and heartbeat check routines to prevent any delay
3110 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303111 dh.lockDevice.RLock()
3112 // Stop the read indication only if it the routine is active
3113 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3114 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3115 // on next execution of the readIndication routine.
3116 if dh.isReadIndicationRoutineActive {
3117 dh.stopIndications <- true
3118 }
3119 dh.lockDevice.RUnlock()
3120
bseenivad1c984b2025-01-09 12:54:44 +05303121 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3122 DeviceId: dh.device.Id,
3123 OperStatus: voltha.OperStatus_REBOOTED,
3124 ConnStatus: voltha.ConnectStatus_REACHABLE,
3125 }); err != nil {
3126 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3127 }
3128
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303129 //raise olt communication failure event
3130 raisedTs := time.Now().Unix()
3131 cloned := proto.Clone(device).(*voltha.Device)
3132 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3133 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3134 dh.device = cloned // update local copy of the device
3135 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3136
Gustavo Silva41af9122022-10-11 11:05:13 -03003137 if err := dh.cleanupDeviceResources(ctx); err != nil {
3138 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3139 } else {
3140 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3141 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003142
3143 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303144 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003145 if dh.isCollectorActive {
3146 dh.stopCollector <- true
3147 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303148 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003149 if dh.isHeartbeatCheckActive {
3150 dh.stopHeartbeatCheck <- true
3151 }
3152 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303153
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003154 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303155
Akash Kankanala041a2122024-10-16 15:49:22 +05303156 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303157 dh.adapterPreviouslyConnected = false
3158 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303159 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3160 if err != nil || childDevices == nil {
3161 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3162 continue
3163 }
3164 if len(childDevices.Items) == 0 {
3165 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3166 break
3167 } else {
3168 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3169 time.Sleep(5 * time.Second)
3170 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303171 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303172 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003173 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303174 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3175 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303176}
3177
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303178// EnableOnuSerialNumber to enable onu serial number
3179func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3180 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3181 onuSerialNumber := device.SerialNumber
3182
3183 // fetch interfaceid from PortNo
3184 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3185
3186 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3187 if err != nil {
3188 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3189 log.Fields{
3190 "devicer-id": dh.device.Id,
3191 "serial-number": onuSerialNumber}, err).Log()
3192 }
3193
3194 onuIntf := &oop.InterfaceOnuSerialNumber{
3195 IntfId: ponID,
3196 OnuSerialNumber: sn,
3197 }
3198 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3199
3200 if err != nil {
3201 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3202 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3203 "device-id": dh.device.Id,
3204 "onu-serial-number": onuSerialNumber}, err)
3205 }
3206 return nil
3207}
3208
3209// DisableOnuSerialNumber to disable onu serial number
3210func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3211 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3212 onuSerialNumber := device.SerialNumber
3213 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3214 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3215 if err != nil {
3216 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3217 log.Fields{
3218 "devicer-id": dh.device.Id,
3219 "serial-number": onuSerialNumber}, err).Log()
3220 }
3221
3222 onuIntf := &oop.InterfaceOnuSerialNumber{
3223 OnuSerialNumber: sn,
3224 IntfId: ponID,
3225 }
3226 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3227
3228 if err != nil {
3229 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3230 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3231 "device-id": dh.device.Id,
3232 "onu-serial-number": onuSerialNumber}, err)
3233 }
3234 return nil
3235}
3236
3237// EnableOnu to enable onu
3238func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3239 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3240 onuSerialNumber := device.SerialNumber
3241 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3242 if InCacheOnuDev == nil {
3243 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3244 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3245 "device-id": dh.device.Id,
3246 "onu-serial-number": onuSerialNumber}, nil)
3247 }
3248 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})
3249
3250 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3251 if err != nil {
3252 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3253 log.Fields{
3254 "device-id": dh.device.Id,
3255 "serial-number": onuSerialNumber}, err).Log()
3256 }
3257
3258 onuIntf := &oop.InterfaceOnuSerialNumber{
3259 OnuSerialNumber: sn,
3260 IntfId: InCacheOnuDev.intfID,
3261 }
3262 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3263 OnuId: InCacheOnuDev.onuID,
3264 IntfIdSerialNum: onuIntf,
3265 }
3266 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3267
3268 if err != nil {
3269 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3270 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3271 "olt-device-id": dh.device.Id,
3272 "onu-serial-number": onuSerialNumber}, err)
3273 }
3274 return nil
3275}
3276
3277// DisableOnu to disable onu
3278func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3279 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3280 onuSerialNumber := device.SerialNumber
3281 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3282 if InCacheOnuDev == nil {
3283 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3284 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3285 "device-id": dh.device.Id,
3286 "onu-serial-number": onuSerialNumber}, nil)
3287 }
3288 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})
3289
3290 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3291 if err != nil {
3292 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3293 log.Fields{
3294 "device-id": dh.device.Id,
3295 "serial-number": onuSerialNumber}, err).Log()
3296 }
3297
3298 onuIntf := &oop.InterfaceOnuSerialNumber{
3299 OnuSerialNumber: sn,
3300 IntfId: InCacheOnuDev.intfID,
3301 }
3302 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3303 OnuId: InCacheOnuDev.onuID,
3304 IntfIdSerialNum: onuIntf,
3305 }
3306 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3307
3308 if err != nil {
3309 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3310 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3311 "olt-device-id": dh.device.Id,
3312 "onu-serial-number": onuSerialNumber}, err)
3313 }
3314 return nil
3315}
3316
kesavand39e0aa32020-01-28 20:58:50 -05003317// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003318func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3319 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3320 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003321}
3322
3323// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003324func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3325 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3326 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003327}
3328
Mahir Gunyela2e68702022-12-07 00:00:42 -08003329// 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 +00003330func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3331 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003332 if port.GetType() == voltha.Port_ETHERNET_NNI {
3333 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003334 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303335 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303336 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003337 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003338 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003339 }
3340 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003341 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003342 ponIntf := &oop.Interface{IntfId: ponID}
3343 var operStatus voltha.OperStatus_Types
bseenivaa1622112025-12-11 18:24:02 +05303344 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
kesavand39e0aa32020-01-28 20:58:50 -05003345 if enablePort {
3346 operStatus = voltha.OperStatus_ACTIVE
bseenivaa1622112025-12-11 18:24:02 +05303347 out, err := dh.Client.EnablePonIf(subCtx, ponIntf)
3348 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003349 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303350 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003351 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003352 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003353 }
3354 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003355 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003356 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003357 } else {
3358 operStatus = voltha.OperStatus_UNKNOWN
bseenivaa1622112025-12-11 18:24:02 +05303359 out, err := dh.Client.DisablePonIf(subCtx, ponIntf)
3360 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003361 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303362 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003363 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003364 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003365 }
3366 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003367 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003368 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003369 }
khenaidoodc2116e2021-10-19 17:33:19 -04003370 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003371 DeviceId: dh.device.Id,
3372 PortType: voltha.Port_PON_OLT,
3373 PortNo: port.PortNo,
3374 OperStatus: operStatus,
3375 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303376 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303377 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003378 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003379 }
3380 return nil
3381}
3382
Mahir Gunyela2e68702022-12-07 00:00:42 -08003383// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003384func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003385 // Disable the port and update the oper_port_status to core
3386 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003387 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003388 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003389 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303390 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303391 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003392 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003393 }
3394 }
3395 }
3396 return nil
3397}
3398
Mahir Gunyela2e68702022-12-07 00:00:42 -08003399// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003400func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3401 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3402 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003403 if port.Type == voltha.Port_ETHERNET_NNI {
3404 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003405 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003406 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003407 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003408 }
3409 }
3410 if port.Type == voltha.Port_PON_OLT {
3411 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003412 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003413 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003414 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003415 }
3416 }
3417 }
3418}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003419
3420// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003421func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003422 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003423 if dh.getDeviceDeletionInProgressFlag() {
3424 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3425 // will reboot, so everything will be reset on the pOLT too.
3426 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3427 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3428 return nil
3429 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303430
3431 if dh.transitionMap.currentDeviceState != deviceStateUp {
3432 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})
3433 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3434 }
3435
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003436 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003437 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003438
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003439 var sn *oop.SerialNumber
3440 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003441 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303442 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003443 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303444 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003445 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003446 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003447
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003448 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303449 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003450 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003451 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3452 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3453 "device-id": dh.device.Id,
3454 "intf-id": intfID,
3455 "onuID": onuID,
3456 "err": err})
3457 } else {
3458 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003459 // Delete flows from device before schedulers and queue
3460 // Clear flowids for gem cache.
3461 removedFlows := []uint64{}
3462 for _, gem := range onuGem.GemPorts {
3463 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3464 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303465 // multiple gem port can have the same flow id
3466 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003467 var alreadyRemoved bool
3468 for _, removedFlowID := range removedFlows {
3469 if removedFlowID == flowID {
3470 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3471 alreadyRemoved = true
3472 break
3473 }
3474 }
3475 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003476 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003477 removedFlows = appendUnique64bit(removedFlows, flowID)
3478 }
3479 }
3480 }
3481 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3482 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003483 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3484 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3485 "device-id": dh.device.Id,
3486 "onu-device": onu,
3487 "err": err})
3488 }
yasin saplibddc2d72022-02-08 13:10:17 +00003489 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003490 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3491 "intf-id": intfID,
3492 "onu-device": onu,
3493 "onu-gem": onuGem,
3494 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303495 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003496 }
3497 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003498 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003499
bseenivaa1622112025-12-11 18:24:02 +05303500 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003501 // Now clear the ONU on the OLT
bseenivaa1622112025-12-11 18:24:02 +05303502 if _, err := dh.Client.DeleteOnu(subCtx, onu); err != nil {
3503 cancel()
Thomas Lee S94109f12020-03-03 16:39:29 +05303504 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303505 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003506 "onu-id": onuID}, err).Log()
3507 }
bseenivaa1622112025-12-11 18:24:02 +05303508 cancel()
balaji.nagarajanbf44ce82026-01-27 08:59:36 +05303509
3510 //free resources only if the deleteonu is successful
3511 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
3512 dh.onus.Delete(onuKey)
3513 dh.discOnus.Delete(onuSn)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003514 return nil
3515}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003516func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3517 flow := &oop.Flow{FlowId: flowID}
3518 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3519 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3520 "device-id": dh.device.Id})
3521 } else {
3522 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3523 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3524 "device-id": dh.device.Id,
3525 "err": err})
3526 }
3527 }
3528}
Girish Gowdracefae192020-03-19 18:14:10 -07003529
3530func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003531 for _, field := range flow_utils.GetOfbFields(flow) {
3532 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003533 return field.GetPort()
3534 }
3535 }
3536 return InvalidPort
3537}
3538
3539func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003540 for _, action := range flow_utils.GetActions(flow) {
3541 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003542 if out := action.GetOutput(); out != nil {
3543 return out.GetPort()
3544 }
3545 }
3546 }
3547 return InvalidPort
3548}
3549
Girish Gowdracefae192020-03-19 18:14:10 -07003550func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3551 inPort := getInPortFromFlow(flow)
3552 outPort := getOutPortFromFlow(flow)
3553
3554 if inPort == InvalidPort || outPort == InvalidPort {
3555 return inPort, outPort
3556 }
3557
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003558 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003559 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003560 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003561 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003562 return uniPort, outPort
3563 }
3564 }
3565 } else {
3566 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003567 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003568 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003569 return inPort, uniPort
3570 }
3571 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003572 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003573 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003574 return uniPort, outPort
3575 }
3576 }
3577 }
3578
3579 return InvalidPort, InvalidPort
3580}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003581
3582func extractOmciTransactionID(omciPkt []byte) uint16 {
3583 if len(omciPkt) > 3 {
3584 d := omciPkt[0:2]
3585 transid := binary.BigEndian.Uint16(d)
3586 return transid
3587 }
3588 return 0
3589}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003590
3591// StoreOnuDevice stores the onu parameters to the local cache.
3592func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3593 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3594 dh.onus.Store(onuKey, onuDevice)
3595}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003596
khenaidoodc2116e2021-10-19 17:33:19 -04003597func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003598 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003599 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003600 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003601 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003602 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003603 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003604 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003605 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3606 return nil, err
3607 }
3608 ID = device.ProxyAddress.GetOnuId()
3609 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3610 valueparam.Onu = &Onu
3611 valueparam.Value = value
3612
3613 // This API is unsupported until agent patch is added
3614 resp.Unsupported = uint32(value)
3615 _ = ctx
3616
3617 // Uncomment this code once agent changes are complete and tests
3618 /*
3619 resp, err = dh.Client.GetValue(ctx, valueparam)
3620 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003621 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003622 return nil, err
3623 }
3624 */
3625
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003626 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 -08003627 return resp, nil
3628}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003629
Akash Kankanala041a2122024-10-16 15:49:22 +05303630func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003631 // Default to NNI
3632 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003633 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003634 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003635 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003636 }
3637 return intfID
3638}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003639
Akash Kankanala041a2122024-10-16 15:49:22 +05303640func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003641 dh.perPonOnuIndicationChannelLock.Lock()
3642 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3643 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003644 return ch.indicationChannel
3645 }
3646 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303647 // We create a buffered channel here to avoid calling function to be blocked
3648 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003649 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003650 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003651 stopChannel: make(chan struct{}),
3652 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003653 dh.perPonOnuIndicationChannel[intfID] = channels
3654 dh.perPonOnuIndicationChannelLock.Unlock()
3655 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003656 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003657}
3658
Mahir Gunyelb0046752021-02-26 13:51:05 -08003659func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3660 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3661 dh.perPonOnuIndicationChannelLock.Lock()
3662 defer dh.perPonOnuIndicationChannelLock.Unlock()
3663 for _, v := range dh.perPonOnuIndicationChannel {
3664 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003665 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003666 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003667}
3668
Mahir Gunyelb0046752021-02-26 13:51:05 -08003669func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3670 ind := onuIndicationMsg{
3671 ctx: ctx,
3672 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003673 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003674 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003675 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303676 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003677}
3678
Mahir Gunyelb0046752021-02-26 13:51:05 -08003679func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003680 for {
3681 select {
3682 // process one indication per onu, before proceeding to the next one
3683 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003684 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003685 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003686 "ind": indication})
3687 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003688 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003689 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003690 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3691 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003692 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003693 }
3694 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003695 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003696 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3697 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003698 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003699 }
3700 }
3701 case <-onuChannels.stopChannel:
3702 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3703 close(onuChannels.indicationChannel)
3704 return
3705 }
3706 }
3707}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003708
3709// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3710// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003711func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003712 if dh.getDeviceDeletionInProgressFlag() {
3713 // The device itself is going to be reset as part of deletion. So nothing to be done.
3714 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3715 return nil
3716 }
3717
Girish Gowdra491a9c62021-01-06 16:43:07 -08003718 // Step1 : Fill McastFlowOrGroupControlBlock
3719 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3720 // Step3 : Wait on response channel for response
3721 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003722 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003723 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3724 errChan := make(chan error)
3725 var groupID uint32
3726 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3727 ctx: ctx,
3728 flowOrGroupAction: action,
3729 flow: flow,
3730 group: group,
3731 errChan: &errChan,
3732 }
3733 if flow != nil {
3734 groupID = flow_utils.GetGroup(flow)
3735 } else if group != nil {
3736 groupID = group.Desc.GroupId
3737 } else {
3738 return errors.New("flow-and-group-both-nil")
3739 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003740 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3741 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3742 // Derive the appropriate go routine to handle the request by a simple module operation.
3743 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3744 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3745 // Wait for handler to return error value
3746 err := <-errChan
3747 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3748 return err
3749 }
3750 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3751 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003752}
3753
3754// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003755func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003756 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003757 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003758 // block on the channel to receive an incoming mcast flow/group
3759 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003760 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3761 if mcastFlowOrGroupCb.flow != nil {
3762 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3763 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3764 log.Fields{"device-id": dh.device.Id,
3765 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003766 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3767 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3768 for _, flMgr := range dh.flowMgr {
3769 if flMgr != nil {
3770 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3771 break
3772 }
3773 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003774 // Pass the return value over the return channel
3775 *mcastFlowOrGroupCb.errChan <- err
3776 } else { // flow remove
3777 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3778 log.Fields{"device-id": dh.device.Id,
3779 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003780 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3781 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3782 for _, flMgr := range dh.flowMgr {
3783 if flMgr != nil {
3784 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3785 break
3786 }
3787 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003788 // Pass the return value over the return channel
3789 *mcastFlowOrGroupCb.errChan <- err
3790 }
3791 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303792 switch mcastFlowOrGroupCb.flowOrGroupAction {
3793 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003794 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3795 log.Fields{"device-id": dh.device.Id,
3796 "groupToAdd": mcastFlowOrGroupCb.group})
3797 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3798 // Pass the return value over the return channel
3799 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303800 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003801 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3802 log.Fields{"device-id": dh.device.Id,
3803 "groupToModify": mcastFlowOrGroupCb.group})
3804 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3805 // Pass the return value over the return channel
3806 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303807 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003808 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3809 log.Fields{"device-id": dh.device.Id,
3810 "groupToRemove": mcastFlowOrGroupCb.group})
3811 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3812 // Pass the return value over the return channel
3813 *mcastFlowOrGroupCb.errChan <- err
3814 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003815 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003816 case <-stopHandler:
3817 dh.mcastHandlerRoutineActive[routineIndex] = false
3818 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003819 }
3820 }
3821}
kesavand62126212021-01-12 04:56:06 -05003822
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003823// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003824func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003825 for i, v := range dh.stopMcastHandlerRoutine {
3826 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003827 select {
3828 case v <- true:
3829 case <-time.After(time.Second * 5):
3830 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3831 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003832 }
3833 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003834
3835 if dh.incomingMcastFlowOrGroup != nil {
3836 for k := range dh.incomingMcastFlowOrGroup {
3837 if dh.incomingMcastFlowOrGroup[k] != nil {
3838 dh.incomingMcastFlowOrGroup[k] = nil
3839 }
3840 }
3841 dh.incomingMcastFlowOrGroup = nil
3842 }
3843
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003844 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003845 logger.Debug(ctx, "stopped all mcast handler routines")
3846}
3847
Akash Kankanala041a2122024-10-16 15:49:22 +05303848// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003849func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003850 singleValResp := extension.SingleGetValueResponse{
3851 Response: &extension.GetValueResponse{
3852 Response: &extension.GetValueResponse_PortCoutners{
3853 PortCoutners: &extension.GetOltPortCountersResponse{},
3854 },
3855 },
3856 }
3857
Akash Kankanala041a2122024-10-16 15:49:22 +05303858 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003859 return &extension.SingleGetValueResponse{
3860 Response: &extension.GetValueResponse{
3861 Status: status,
3862 ErrReason: reason,
3863 },
3864 }
3865 }
3866
3867 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3868 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303869 // send error response
kesavand62126212021-01-12 04:56:06 -05003870 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3871 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3872 }
3873 statIndChn := make(chan bool, 1)
3874 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3875 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303876 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003877
3878 go func() {
bseenivaa1622112025-12-11 18:24:02 +05303879 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3880 _, err := dh.Client.CollectStatistics(subCtx, new(oop.Empty))
kesavand62126212021-01-12 04:56:06 -05003881 if err != nil {
3882 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3883 }
bseenivaa1622112025-12-11 18:24:02 +05303884 cancel()
kesavand62126212021-01-12 04:56:06 -05003885 }()
3886 select {
3887 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303888 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003889 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3890 case <-time.After(oltPortInfoTimeout * time.Second):
3891 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3892 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3893 case <-ctx.Done():
3894 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3895 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3896 }
mgouda86543582025-10-29 20:58:16 +05303897 switch oltPortInfo.PortType {
3898 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303899 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003900 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003901 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3902 cmnni := dh.portStats.collectNNIMetrics(intfID)
3903 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303904 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003905 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3906 }
3907 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3908 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303909 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003910 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003911 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003912 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3913 cmpon := dh.portStats.collectPONMetrics(intfID)
3914 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303915 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003916 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3917 }
3918 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3919 return &singleValResp
3920 }
3921 }
3922 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3923}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303924
Akash Kankanala041a2122024-10-16 15:49:22 +05303925//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303926func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303927 singleValResp := extension.SingleGetValueResponse{
3928 Response: &extension.GetValueResponse{
3929 Status: extension.GetValueResponse_OK,
3930 Response: &extension.GetValueResponse_OffloadedAppsStats{
3931 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3932 },
3933 },
3934 }
3935
3936 return &singleValResp
3937}
3938
Akash Kankanala041a2122024-10-16 15:49:22 +05303939//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303940func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303941 singleValResp := extension.SingleSetValueResponse{
3942 Response: &extension.SetValueResponse{
3943 Status: extension.SetValueResponse_OK,
3944 },
3945 }
3946
3947 return &singleValResp
3948}
3949
Akash Kankanala041a2122024-10-16 15:49:22 +05303950//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303951func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303952 singleValResp := extension.SingleSetValueResponse{
3953 Response: &extension.SetValueResponse{
3954 Status: extension.SetValueResponse_OK,
3955 },
3956 }
3957
3958 return &singleValResp
3959}
3960
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303961func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303962 singleValResp := extension.SingleGetValueResponse{
3963 Response: &extension.GetValueResponse{
3964 Response: &extension.GetValueResponse_OnuPonCounters{
3965 OnuPonCounters: &extension.GetOnuCountersResponse{},
3966 },
3967 },
3968 }
3969
Akash Kankanala041a2122024-10-16 15:49:22 +05303970 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303971 return &extension.SingleGetValueResponse{
3972 Response: &extension.GetValueResponse{
3973 Status: status,
3974 ErrReason: reason,
3975 },
3976 }
3977 }
3978 intfID := onuPonInfo.IntfId
3979 onuID := onuPonInfo.OnuId
3980 onuKey := dh.formOnuKey(intfID, onuID)
3981
3982 if _, ok := dh.onus.Load(onuKey); !ok {
3983 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3984 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3985 }
3986 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3987 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3988 if cmnni == nil {
3989 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3990 }
3991 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3992 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303993}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003994
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303995func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3996 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3997 if err != nil {
3998 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3999 return nil, err
4000 }
4001 if onuGemInfo != nil {
4002 if len(onuGemInfo.UniPorts) == 0 {
4003 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
4004 return nil, err
4005 }
4006 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
4007 return onuGemInfo, nil
4008 }
4009 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
4010 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
4011}
4012
4013func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
4014 var err error
4015 var allocStats *oop.OnuAllocIdStatistics
4016 var onuGemStats *oop.GemPortStatistics
4017 for _, uni := range onuGemInfo.UniPorts {
4018 uniID := plt.UniIDFromPortNum(uni)
4019 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
4020 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
4021 if len(tpIDs) == 0 {
4022 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
4023 continue
4024 }
4025 for _, tpId := range tpIDs {
4026 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
4027 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
4028 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
4029 if techProfileInstance != nil {
4030 switch tpInst := techProfileInstance.(type) {
4031 case *tp_pb.TechProfileInstance:
4032 allocId := tpInst.UsScheduler.AllocId
4033 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
bseenivaa1622112025-12-11 18:24:02 +05304034 allocCtx, allocCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4035 allocStats, err = dh.Client.GetAllocIdStatistics(allocCtx, &onuAllocPkt)
4036 allocCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304037 if err != nil {
4038 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
4039 return err
4040 }
4041 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
4042 allocIdInfo.AllocId = allocStats.AllocId
4043 allocIdInfo.RxBytes = allocStats.RxBytes
4044
4045 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
4046
4047 gemPorts := tpInst.UpstreamGemPortAttributeList
4048 for _, gem := range gemPorts {
4049 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
bseenivaa1622112025-12-11 18:24:02 +05304050 gemCtx, gemCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4051 onuGemStats, err = dh.Client.GetGemPortStatistics(gemCtx, &onuGemPkt)
4052 gemCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304053 if err != nil {
4054 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
4055 return err
4056 }
4057 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
4058 gemStatsInfo.GemId = onuGemStats.GemportId
4059 gemStatsInfo.RxBytes = onuGemStats.RxBytes
4060 gemStatsInfo.RxPackets = onuGemStats.RxPackets
4061 gemStatsInfo.TxBytes = onuGemStats.TxBytes
4062 gemStatsInfo.TxPackets = onuGemStats.TxPackets
4063
4064 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
4065 }
4066 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
4067
4068 default:
4069 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4070 return err
4071 }
4072 } else {
4073 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4074 continue
4075 }
4076 }
4077 }
4078 return err
4079}
4080
4081//nolint:unparam
4082func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4083 singleValResp := extension.SingleGetValueResponse{
4084 Response: &extension.GetValueResponse{
4085 Status: extension.GetValueResponse_OK,
4086 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4087 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4088 },
4089 },
4090 }
4091 errResp := func(status extension.GetValueResponse_Status,
4092 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4093 return &extension.SingleGetValueResponse{
4094 Response: &extension.GetValueResponse{
4095 Status: status,
4096 ErrReason: reason,
4097 },
4098 }
4099 }
4100
4101 var intfID, onuID uint32
4102 if onuDevice != nil {
4103 onuID = onuDevice.ProxyAddress.OnuId
4104 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4105 }
4106
4107 onuKey := dh.formOnuKey(intfID, onuID)
4108 if _, ok := dh.onus.Load(onuKey); !ok {
4109 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4110 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4111 }
4112 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4113
4114 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4115 if err == nil {
4116 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4117 if err != nil {
4118 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4119 }
4120 } else {
4121 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4122 }
4123 return &singleValResp
4124}
4125
nikesh.krishnanc8473432023-06-14 12:14:54 +05304126func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304127 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
bseenivaa1622112025-12-11 18:24:02 +05304128 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4129 OnuInfo, err := dh.Client.GetOnuInfo(subCtx, &Onu)
4130 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304131 if err != nil {
4132 return nil, err
4133 }
4134 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304135}
4136
4137func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304138 Intf := oop.Interface{IntfId: intfID}
bseenivaa1622112025-12-11 18:24:02 +05304139 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4140 IntfInfo, err := dh.Client.GetPonInterfaceInfo(subCtx, &Intf)
4141 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304142 if err != nil {
4143 return nil, err
4144 }
4145 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304146}
4147
Gamze Abaka85e9a142021-05-26 13:41:39 +00004148func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004149 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
bseenivaa1622112025-12-11 18:24:02 +05304150 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4151 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4152 cancel()
Gamze Abaka85e9a142021-05-26 13:41:39 +00004153 if err != nil {
4154 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4155 return generateSingleGetValueErrorResponse(err)
4156 }
4157 return &extension.SingleGetValueResponse{
4158 Response: &extension.GetValueResponse{
4159 Status: extension.GetValueResponse_OK,
4160 Response: &extension.GetValueResponse_RxPower{
4161 RxPower: &extension.GetRxPowerResponse{
4162 IntfId: rxPowerRequest.IntfId,
4163 OnuId: rxPowerRequest.OnuId,
4164 Status: rxPower.Status,
4165 FailReason: rxPower.FailReason.String(),
4166 RxPower: rxPower.RxPowerMeanDbm,
4167 },
4168 },
4169 },
4170 }
4171}
4172
praneeth nalmas55616d62023-02-06 09:19:18 +05304173func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304174 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304175 return &extension.SingleGetValueResponse{
4176 Response: &extension.GetValueResponse{
4177 Status: status,
4178 ErrReason: reason,
4179 },
4180 }
4181 }
4182
4183 resp := extension.SingleGetValueResponse{
4184 Response: &extension.GetValueResponse{
4185 Status: extension.GetValueResponse_OK,
4186 Response: &extension.GetValueResponse_OltRxPower{
4187 OltRxPower: &extension.GetOltRxPowerResponse{},
4188 },
4189 },
4190 }
4191
4192 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4193 portLabel := OltRxPowerRequest.PortLabel
4194 serialNumber := OltRxPowerRequest.OnuSn
4195
4196 portInfo := strings.Split(portLabel, "-")
4197 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4198
4199 if err != nil {
4200 logger.Errorw(ctx, "getPONRxPower 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, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4206 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4207 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304208
4209 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304210 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4211 if onuDev != nil {
bseenivaa1622112025-12-11 18:24:02 +05304212 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
praneeth nalmas55616d62023-02-06 09:19:18 +05304213 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
bseenivaa1622112025-12-11 18:24:02 +05304214 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4215 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304216 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304217 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4218 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304219 }
4220
4221 rxPowerValue := extension.RxPower{}
4222 rxPowerValue.OnuSn = onuDev.serialNumber
4223 rxPowerValue.Status = rxPower.GetStatus()
4224 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4225 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4226
4227 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304228 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304229 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4230 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4231 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304232 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304233 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304234 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304235 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
bseenivaa1622112025-12-11 18:24:02 +05304236 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4237 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4238 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304239 if err != nil {
4240 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4241 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304242 rxPowerValue := extension.RxPower{}
4243 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4244 rxPowerValue.Status = rxPower.GetStatus()
4245 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4246 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4247
4248 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4249 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304250 }
4251 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4252 return true
4253 })
4254 }
4255 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4256 return &resp
4257}
4258
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304259func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4260 errResp := func(status extension.GetValueResponse_Status,
4261 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4262 return &extension.SingleGetValueResponse{
4263 Response: &extension.GetValueResponse{
4264 Status: status,
4265 ErrReason: reason,
4266 },
4267 }
4268 }
4269
4270 resp := extension.SingleGetValueResponse{
4271 Response: &extension.GetValueResponse{
4272 Status: extension.GetValueResponse_OK,
4273 Response: &extension.GetValueResponse_OltPonStatsResponse{
4274 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4275 },
4276 },
4277 }
4278
4279 portLabel := ponStatsRequest.GetPortLabel()
4280 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4281
4282 portInfo := strings.Split(portLabel, "-")
4283 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4284
4285 if err != nil {
4286 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4287 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4288 }
4289
4290 if portInfo[0] != "pon" {
4291 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4292 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4293 }
4294
4295 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304296 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4297 ponStats, err := dh.Client.GetPonPortStatistics(subCtx, &Interface)
4298 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304299 if err != nil {
4300 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4301 return generateSingleGetValueErrorResponse(err)
4302 }
4303
4304 ponPortStats := resp.Response.GetOltPonStatsResponse()
4305 ponPortStats.PonPort = uint32(portNumber)
4306 ponPortStats.PortStatistics = ponStats
4307
4308 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4309 return &resp
4310}
4311
4312func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4313 errResp := func(status extension.GetValueResponse_Status,
4314 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4315 return &extension.SingleGetValueResponse{
4316 Response: &extension.GetValueResponse{
4317 Status: status,
4318 ErrReason: reason,
4319 },
4320 }
4321 }
4322
4323 resp := extension.SingleGetValueResponse{
4324 Response: &extension.GetValueResponse{
4325 Status: extension.GetValueResponse_OK,
4326 Response: &extension.GetValueResponse_OltNniStatsResponse{
4327 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4328 },
4329 },
4330 }
4331
4332 portLabel := nniStatsRequest.GetPortLabel()
4333 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4334
4335 portInfo := strings.Split(portLabel, "-")
4336 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4337
4338 if err != nil {
4339 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4340 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4341 }
4342
4343 if portInfo[0] != "nni" {
4344 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4345 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4346 }
4347
4348 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304349 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4350 nniStats, err := dh.Client.GetNniPortStatistics(subCtx, &Interface)
4351 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304352 if err != nil {
4353 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4354 return generateSingleGetValueErrorResponse(err)
4355 }
4356
4357 nniPortStats := resp.Response.GetOltNniStatsResponse()
4358 nniPortStats.NniPort = uint32(portNumber)
4359 nniPortStats.PortStatistics = nniStats
4360
4361 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4362 return &resp
4363}
4364
Akash Kankanala041a2122024-10-16 15:49:22 +05304365// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004366func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304367 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004368 return &extension.SingleGetValueResponse{
4369 Response: &extension.GetValueResponse{
4370 Status: status,
4371 ErrReason: reason,
4372 },
4373 }
4374 }
4375
4376 if err != nil {
4377 if e, ok := status.FromError(err); ok {
4378 switch e.Code() {
4379 case codes.Internal:
4380 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4381 case codes.DeadlineExceeded:
4382 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4383 case codes.Unimplemented:
4384 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4385 case codes.NotFound:
4386 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4387 }
4388 }
4389 }
4390
4391 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4392}
khenaidoo106c61a2021-08-11 18:05:46 -04004393
4394/*
4395Helper functions to communicate with Core
4396*/
4397
4398func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4399 cClient, err := dh.coreClient.GetCoreServiceClient()
4400 if err != nil || cClient == nil {
4401 return nil, err
4402 }
4403 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4404 defer cancel()
4405 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4406}
4407
khenaidoodc2116e2021-10-19 17:33:19 -04004408func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004409 cClient, err := dh.coreClient.GetCoreServiceClient()
4410 if err != nil || cClient == nil {
4411 return nil, err
4412 }
4413 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4414 defer cancel()
4415 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4416}
4417
khenaidoodc2116e2021-10-19 17:33:19 -04004418func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004419 cClient, err := dh.coreClient.GetCoreServiceClient()
4420 if err != nil || cClient == nil {
4421 return err
4422 }
4423 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4424 defer cancel()
4425 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4426 return err
4427}
4428
4429func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4430 cClient, err := dh.coreClient.GetCoreServiceClient()
4431 if err != nil || cClient == nil {
4432 return nil, err
4433 }
4434 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4435 defer cancel()
4436 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4437}
4438
4439func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4440 cClient, err := dh.coreClient.GetCoreServiceClient()
4441 if err != nil || cClient == nil {
4442 return nil, err
4443 }
4444 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4445 defer cancel()
4446 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4447}
4448
4449func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4450 cClient, err := dh.coreClient.GetCoreServiceClient()
4451 if err != nil || cClient == nil {
4452 return err
4453 }
4454 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4455 defer cancel()
4456 _, err = cClient.DeviceUpdate(subCtx, device)
4457 return err
4458}
4459
khenaidoodc2116e2021-10-19 17:33:19 -04004460func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004461 cClient, err := dh.coreClient.GetCoreServiceClient()
4462 if err != nil || cClient == nil {
4463 return nil, err
4464 }
4465 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4466 defer cancel()
4467 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4468}
4469
khenaidoodc2116e2021-10-19 17:33:19 -04004470func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004471 cClient, err := dh.coreClient.GetCoreServiceClient()
4472 if err != nil || cClient == nil {
4473 return err
4474 }
4475 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4476 defer cancel()
4477 _, err = cClient.SendPacketIn(subCtx, pkt)
4478 return err
4479}
4480
4481func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4482 cClient, err := dh.coreClient.GetCoreServiceClient()
4483 if err != nil || cClient == nil {
4484 return err
4485 }
4486 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4487 defer cancel()
4488 _, err = cClient.PortCreated(subCtx, port)
4489 return err
4490}
4491
khenaidoodc2116e2021-10-19 17:33:19 -04004492func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004493 cClient, err := dh.coreClient.GetCoreServiceClient()
4494 if err != nil || cClient == nil {
4495 return err
4496 }
4497 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4498 defer cancel()
4499 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4500 return err
4501}
4502
khenaidoodc2116e2021-10-19 17:33:19 -04004503func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004504 cClient, err := dh.coreClient.GetCoreServiceClient()
4505 if err != nil || cClient == nil {
4506 return err
4507 }
4508 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4509 defer cancel()
4510 _, err = cClient.PortStateUpdate(subCtx, portState)
4511 return err
4512}
4513
khenaidoodc2116e2021-10-19 17:33:19 -04004514func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004515 cClient, err := dh.coreClient.GetCoreServiceClient()
4516 if err != nil || cClient == nil {
4517 return nil, err
4518 }
4519 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4520 defer cancel()
4521 return cClient.GetDevicePort(subCtx, portFilter)
4522}
4523
nikesh.krishnanc8473432023-06-14 12:14:54 +05304524func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4525 cClient, err := dh.coreClient.GetCoreServiceClient()
4526 if err != nil || cClient == nil {
4527 return nil, err
4528 }
4529 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4530 defer cancel()
4531 return cClient.GetPorts(subCtx, portFilter)
4532}
4533
khenaidoo106c61a2021-08-11 18:05:46 -04004534/*
4535Helper functions to communicate with child adapter
4536*/
4537
khenaidoodc2116e2021-10-19 17:33:19 -04004538func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004539 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4540 if err != nil || aClient == nil {
4541 return err
4542 }
4543 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4544 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4545 defer cancel()
4546 _, err = aClient.OmciIndication(subCtx, response)
4547 return err
4548}
4549
khenaidoodc2116e2021-10-19 17:33:19 -04004550func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004551 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4552 if err != nil || aClient == nil {
4553 return err
4554 }
4555 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4556 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4557 defer cancel()
4558 _, err = aClient.OnuIndication(subCtx, onuInd)
4559 return err
4560}
4561
khenaidoodc2116e2021-10-19 17:33:19 -04004562func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004563 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4564 if err != nil || aClient == nil {
4565 return err
4566 }
4567 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4568 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4569 defer cancel()
4570 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4571 return err
4572}
4573
khenaidoodc2116e2021-10-19 17:33:19 -04004574func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004575 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4576 if err != nil || aClient == nil {
4577 return err
4578 }
4579 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4580 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4581 defer cancel()
4582 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4583 return err
4584}
4585
khenaidoodc2116e2021-10-19 17:33:19 -04004586func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004587 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4588 if err != nil || aClient == nil {
4589 return err
4590 }
4591 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4592 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4593 defer cancel()
4594 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4595 return err
4596}
4597
4598/*
4599Helper functions for remote communication
4600*/
4601
4602// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4603// supports is deleted
4604func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05304605 logger.Debugw(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004606
4607 dh.lockChildAdapterClients.Lock()
4608 defer dh.lockChildAdapterClients.Unlock()
4609 if _, ok := dh.childAdapterClients[endpoint]; ok {
4610 // Already set
4611 return nil
4612 }
4613
4614 // Setup child's adapter grpc connection
4615 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004616 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4617 dh.cfg.AdapterEndpoint,
4618 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004619 "onu_inter_adapter_service.OnuInterAdapterService",
4620 dh.onuInterAdapterRestarted,
4621 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004622 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4623 return err
4624 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304625 retryCodes := []codes.Code{
4626 codes.Unavailable, // server is currently unavailable
4627 codes.DeadlineExceeded, // deadline for the operation was exceeded
4628 }
4629 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4630 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 -04004631
nikesh.krishnand9812542023-08-01 18:31:39 +05304632 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004633 // Wait until we have a connection to the child adapter.
4634 // Unlimited retries or until context expires
4635 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4636 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4637 for {
4638 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4639 if err == nil && client != nil {
4640 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4641 break
4642 }
4643 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4644 // Backoff
4645 if err = backoff.Backoff(subCtx); err != nil {
4646 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4647 break
4648 }
4649 }
4650 return nil
4651}
4652
khenaidoodc2116e2021-10-19 17:33:19 -04004653func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004654 // First check from cache
4655 dh.lockChildAdapterClients.RLock()
4656 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4657 dh.lockChildAdapterClients.RUnlock()
4658 return cgClient.GetOnuInterAdapterServiceClient()
4659 }
4660 dh.lockChildAdapterClients.RUnlock()
4661
4662 // Set the child connection - can occur on restarts
4663 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4664 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4665 cancel()
4666 if err != nil {
4667 return nil, err
4668 }
4669
4670 // Get the child client now
4671 dh.lockChildAdapterClients.RLock()
4672 defer dh.lockChildAdapterClients.RUnlock()
4673 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4674 return cgClient.GetOnuInterAdapterServiceClient()
4675 }
4676 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4677}
4678
4679func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4680 dh.lockChildAdapterClients.Lock()
4681 defer dh.lockChildAdapterClients.Unlock()
4682 for key, client := range dh.childAdapterClients {
4683 client.Stop(ctx)
4684 delete(dh.childAdapterClients, key)
4685 }
4686}
4687
khenaidooefff76e2021-12-15 16:51:30 -05004688// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4689func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4690 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004691 return nil
4692}
4693
khenaidooefff76e2021-12-15 16:51:30 -05004694// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4695func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4696 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004697 return nil
4698 }
khenaidooefff76e2021-12-15 16:51:30 -05004699 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004700}
Girish Gowdra950326e2021-11-05 12:43:24 -07004701
4702func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4703 dh.lockDevice.Lock()
4704 defer dh.lockDevice.Unlock()
4705 dh.isDeviceDeletionInProgress = flag
4706}
4707
4708func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4709 dh.lockDevice.RLock()
4710 defer dh.lockDevice.RUnlock()
4711 return dh.isDeviceDeletionInProgress
4712}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004713
4714// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4715// Returns false if waiting timed out.
4716func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4717 c := make(chan struct{})
4718 go func() {
4719 defer close(c)
4720 wg.Wait()
4721 }()
4722 select {
4723 case <-c:
4724 return true // completed normally
4725 case <-time.After(timeout):
4726 return false // timed out
4727 }
4728}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304729
4730func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4731 val, err := json.Marshal(signature)
4732 if err != nil {
4733 logger.Error(ctx, "failed-to-marshal")
4734 return
4735 }
4736 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4737 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4738 }
4739}
4740
4741func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4742 var signature uint32
4743
4744 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4745 if er == nil {
4746 if Value != nil {
4747 Val, er := kvstore.ToByte(Value.Value)
4748 if er != nil {
4749 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4750 return signature
4751 }
4752 if er = json.Unmarshal(Val, &signature); er != nil {
4753 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4754 return signature
4755 }
4756 }
4757 }
4758 return signature
4759}
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00004760
4761func (dh *DeviceHandler) UpdateDevice(ctx context.Context, updateDevice *voltha.UpdateDevice) {
4762 var dhCtx context.Context
4763 logger.Debug(ctx, "UpdateDevice called", log.Fields{"deviceConfig": updateDevice})
4764 dh.lockDevice.Lock()
4765 if dh.transitionHandlerCancel != nil {
4766 dh.transitionHandlerCancel() //if the previous device transition was grpc blocked on old IP,this make that handler return/exit.
4767 dh.transitionHandlerCancel = nil
4768 }
4769 err := updateDeviceAddress(dh.device, updateDevice) //update the device handler with the new device which would have newIP
4770 if err != nil {
4771 dh.lockDevice.Unlock()
4772 logger.Errorw(ctx, "failed-to-update-device-address", log.Fields{"error": err})
4773 return
4774 }
4775 connectStatus := dh.device.ConnectStatus
4776 dhCtx, dh.transitionHandlerCancel = context.WithCancel(context.Background())
4777 dh.lockDevice.Unlock()
4778 if connectStatus == voltha.ConnectStatus_REACHABLE {
4779 dh.updateStateUnreachable(dhCtx)
4780 } else {
4781 dh.transitionMap.Handle(dhCtx, DeviceInit)
4782 }
4783}
4784
4785func updateDeviceAddress(device *voltha.Device, deviceConfig *voltha.UpdateDevice) error {
4786 switch addr := deviceConfig.Address.(type) {
4787 case *voltha.UpdateDevice_Ipv4Address:
4788 if current, ok := device.Address.(*voltha.Device_Ipv4Address); ok {
4789 if current.Ipv4Address == addr.Ipv4Address {
4790 return fmt.Errorf("no-change-in-IPV4-device-address")
4791 }
4792 device.Address = &voltha.Device_Ipv4Address{Ipv4Address: addr.Ipv4Address}
4793 }
4794 case *voltha.UpdateDevice_Ipv6Address:
4795 if current, ok := device.Address.(*voltha.Device_Ipv6Address); ok {
4796 if current.Ipv6Address == addr.Ipv6Address {
4797 return fmt.Errorf("no-change-in-IPV6-device-address")
4798 }
4799 device.Address = &voltha.Device_Ipv6Address{Ipv6Address: addr.Ipv6Address}
4800 }
4801 case *voltha.UpdateDevice_HostAndPort:
4802 if current, ok := device.Address.(*voltha.Device_HostAndPort); ok {
4803 if current.HostAndPort == addr.HostAndPort {
4804 return fmt.Errorf("no-change-in-HostAndPort-device-address")
4805 }
4806 device.Address = &voltha.Device_HostAndPort{HostAndPort: addr.HostAndPort}
4807 }
4808 default:
4809 return fmt.Errorf("invalid-device-config-address-type")
4810 }
4811 return nil
4812}