blob: ea6eedf17e310f57fdb2824a1cf55fd238c1185d [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)
balaji.nagarajan7ca68b52026-02-01 11:28:43 +0530957 case onuLosFromOlt.String() == "OFF" && onuConnectStatusFromCore.String() == "REACHABLE":
958 //Nothing to Indicate , just add the onu to the device handler onu cache
959 deviceType := onuDeviceFromCore.Type
960 deviceID := onuDeviceFromCore.Id
961 proxyDeviceID := onuDeviceFromCore.ProxyAddress.DeviceId
962 onuKey := dh.formOnuKey(intfID, onuID)
963 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDeviceFromCore.SerialNumber, onuID, intfID, proxyDeviceID, false, onuDeviceFromCore.AdapterEndpoint))
nikesh.krishnanc8473432023-06-14 12:14:54 +0530964 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530965 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530966 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530967 return nil
968}
969
970func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
971 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
972 DeviceId: dh.device.Id,
973 PortType: voltha.Port_PON_OLT,
974 })
975 if err != nil {
976 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530977 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530978 }
979 for _, portFromCore := range portsFromCore.Items {
980 portNum := portFromCore.GetPortNo()
981 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
982 portOperStatusFromCore := portFromCore.OperStatus
983 portAdminStateFromCore := portFromCore.AdminState
984 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
985 if err != nil {
986 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
987 } else {
988 portLosFromOlt := ponPortFromOlt.GetLos()
989 portStateFromOlt := ponPortFromOlt.GetState()
990 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
991 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
992 "portStateFromOlt": portStateFromOlt.String(),
993 "portOperStatusFromCore": portOperStatusFromCore.String(),
994 "device-id": dh.device.Id,
995 "port": portNum})
996 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
997 raisedTs := time.Now().Unix()
998 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530999 }
1000 switch {
1001 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
1002 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
1003 "portStateFromOlt": portStateFromOlt.String(),
1004 "portOperStatusFromCore": portOperStatusFromCore.String(),
1005 "device-id": dh.device.Id,
1006 "port": portNum})
1007 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
1008 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
1009 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
1010 "portStateFromOlt": portStateFromOlt.String(),
1011 "portOperStatusFromCore": portOperStatusFromCore.String(),
1012 "device-id": dh.device.Id,
1013 "port": portNum})
1014 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
1015 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
1016 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
1017 "device-id": dh.device.Id,
1018 "port": portNum})
1019 default:
1020 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
1021 "portStateFromOlt": portStateFromOlt.String(),
1022 "portOperStatusFromCore": portOperStatusFromCore.String(),
1023 "device-id": dh.device.Id,
1024 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301025 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301026 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301027 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301028 return nil
1029}
1030
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301031// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301032func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +05301033 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +05301034 // Declare deviceStateFilter to be used later
1035 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +05301036 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001037 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +05301038 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301039 if err != nil {
1040 return fmt.Errorf("failed to get device from core: %w", err)
1041 }
1042 logger.Info(ctx, "Device state", log.Fields{
1043 "device-id": device.Id,
1044 "CurrOperStatus": device.OperStatus,
1045 "CurrConnStatus": device.ConnectStatus,
1046 })
1047 // Perform cleanup if the device's operational status is REBOOTED
1048 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
1049 // Log the device's operational status if it's REBOOTED
1050 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
1051 "device-id": device.Id,
1052 "OperStatus": device.OperStatus,
1053 })
1054 dh.lockDevice.RLock()
1055 // Stop the read indication only if it the routine is active
1056 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1057 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1058 // on next execution of the readIndication routine.
1059 if dh.isHeartbeatCheckActive {
1060 dh.stopHeartbeatCheck <- true
1061 }
1062 if dh.isReadIndicationRoutineActive {
1063 dh.stopIndications <- true
1064 }
bseenivaaa9165b2025-09-18 17:28:12 +05301065 if dh.isCollectorActive {
1066 dh.stopCollector <- true
1067 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301068 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +05301069 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301070 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
1071 return fmt.Errorf("cleanup device resources failed: %w", err)
1072 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301073 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301074 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1075 }
bseenivaaa9165b2025-09-18 17:28:12 +05301076 dh.collectorWaitGroup.Add(1)
1077 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301078 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301079 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +05301080 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
1081 // Log the device's operational status if it's RECONCILING
1082 logger.Info(ctx, "Device is being reconciled", log.Fields{
1083 "device-id": device.Id,
1084 "OperStatus": device.OperStatus,
1085 })
1086
1087 // Perform reconciliation steps
1088 err = dh.reconcileOnus(ctx)
1089 if err != nil {
1090 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1091 }
1092 err = dh.reconcilePonPorts(ctx)
1093 if err != nil {
1094 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301095 }
1096 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001097 // instantiate the mcast handler routines.
1098 for i := range dh.incomingMcastFlowOrGroup {
1099 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1100 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1101 if !dh.mcastHandlerRoutineActive[i] {
1102 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1103 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1104 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1105 // for incoming mcast flow/group to be processed serially.
1106 dh.mcastHandlerRoutineActive[i] = true
1107 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1108 }
1109 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301110 // Create DeviceStateFilter with the desired operational and connection statuses
1111 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001112 DeviceId: dh.device.Id,
1113 OperStatus: voltha.OperStatus_ACTIVE,
1114 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301115 }
1116 // Log DeviceStateFilter for debugging purposes
1117 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1118 "DeviceId": deviceStateFilter.DeviceId,
1119 "OperStatus": deviceStateFilter.OperStatus,
1120 "ConnStatus": deviceStateFilter.ConnStatus,
1121 })
1122 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301123 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001124 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001125 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001126
Akash Kankanala041a2122024-10-16 15:49:22 +05301127 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001128 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1129 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301130
1131 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1132 if err != nil {
1133 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1134 }
1135 dh.populateActivePorts(ctx, ports.Items)
1136 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1137 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1138 }
1139
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001140 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001141 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1142
Girish Gowdru0c588b22019-04-23 23:24:56 -04001143 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301144}
1145
1146// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301147func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001148 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001149
khenaidoo106c61a2021-08-11 18:05:46 -04001150 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001151 if err != nil || device == nil {
1152 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001153 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001154 }
1155
1156 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001157
Akash Kankanala041a2122024-10-16 15:49:22 +05301158 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001159 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001160 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001161 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001162 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001163
khenaidoodc2116e2021-10-19 17:33:19 -04001164 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001165 DeviceId: cloned.Id,
1166 OperStatus: cloned.OperStatus,
1167 ConnStatus: cloned.ConnectStatus,
1168 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001169 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001170 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001171
Akash Kankanala041a2122024-10-16 15:49:22 +05301172 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001173 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001174 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001175 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001176 }
1177 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001178 // Update onu state as down in onu adapter
1179 onuInd := oop.OnuIndication{}
1180 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001181
1182 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1183 if err != nil {
1184 return err
1185 }
1186 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001187 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001188 DeviceId: onuDevice.Id,
1189 OnuIndication: &onuInd,
1190 })
1191 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001193 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001194 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 "onu-indicator": onuInd,
1196 "device-type": onuDevice.Type,
1197 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301198 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001199 } else {
1200 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 -07001201 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001202 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001203 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001204 /* Discovered ONUs entries need to be cleared , since after OLT
1205 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301206 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001207 dh.lockDevice.Unlock()
1208
Neha Sharma96b7bf22020-06-15 10:37:32 +00001209 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001210 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301211}
1212
1213// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301214func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001215 var err error
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001216 dh.lockDevice.RLock()
1217 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.
1218 dh.lockDevice.RUnlock()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001219 // if the connection is already available, close the previous connection (olt reboot case)
1220 if dh.clientCon != nil {
1221 if err = dh.clientCon.Close(); err != nil {
1222 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1223 } else {
1224 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1225 }
1226 }
1227
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001228 logger.Debugw(ctx, "Dialing grpc", log.Fields{"device-id": dh.device.Id, "host-and-port": hostAndPort})
Abhay Kumard3f18512025-12-09 07:51:12 +00001229 grpc_prometheus.EnableClientHandlingTimeHistogram()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001230 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001231 dh.clientCon, err = grpc.DialContext(ctx, hostAndPort,
Girish Kumar93e91742020-07-27 16:43:19 +00001232 grpc.WithInsecure(),
1233 grpc.WithBlock(),
1234 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001235 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001236 grpc_prometheus.StreamClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001237 )),
1238 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001239 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001240 grpc_prometheus.UnaryClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001241 )))
1242
1243 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301244 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301245 "device-id": dh.device.Id,
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001246 "host-and-port": hostAndPort}, err)
Akash Sonif49299a2024-04-25 12:06:37 +05301247 }
1248
1249 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001250 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
Akash Sonif49299a2024-04-25 12:06:37 +05301251 DeviceId: dh.device.Id,
1252 OperStatus: voltha.OperStatus_RECONCILING,
1253 ConnStatus: voltha.ConnectStatus_REACHABLE,
1254 }); err != nil {
1255 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1256 }
1257 // 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
1258 // locally cached copy of the device struct.
1259 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1260 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1261 }
1262
Girish Gowdru0c588b22019-04-23 23:24:56 -04001263 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301264}
1265
1266// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301267func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001268 dh.Client = oop.NewOpenoltClient(dh.clientCon)
bseenivaa20d6c32026-01-11 21:51:19 +05301269 // decoupling it to avoid blocking state machine transition
1270 go dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001271 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301272}
1273
1274// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301275func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301276 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001277 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001278
1279 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001280 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301281 if err != nil || device == nil {
1282 /*TODO: needs to handle error scenarios */
1283 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1284 }
1285 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001286 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001287
1288 cloned := proto.Clone(device).(*voltha.Device)
1289 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1290 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1291 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001292
khenaidoodc2116e2021-10-19 17:33:19 -04001293 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001294 DeviceId: cloned.Id,
1295 OperStatus: cloned.OperStatus,
1296 ConnStatus: cloned.ConnectStatus,
1297 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301298 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 -04001299 }
1300
bseenivaa1622112025-12-11 18:24:02 +05301301 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Chaitrashree G S44124192019-08-07 20:21:36 -04001302 // 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 +05301303 _, err = dh.Client.DisableOlt(subCtx, new(oop.Empty))
1304 cancel()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001305 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301306 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001307 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001308 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1309 // all the modules initialized and ready to handle incoming ONUs.
1310
Thomas Lee S985938d2020-05-04 11:40:41 +05301311 err = dh.initializeDeviceHandlerModules(ctx)
1312 if err != nil {
1313 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 -04001314 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001315
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001316 go startHeartbeatCheck(ctx, dh)
1317
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001318 return nil
1319 }
1320
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001321 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301322 logger.Error(ctx, "device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1323 cloned := proto.Clone(device).(*voltha.Device)
1324 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1325 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1326 dh.device = cloned
1327
1328 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
1329 DeviceId: cloned.Id,
1330 OperStatus: cloned.OperStatus,
1331 ConnStatus: cloned.ConnectStatus,
1332 }); err != nil {
1333 logger.Error(ctx, "device-state-update-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1334 }
1335 // decoupling it to avoid blocking state machine transition
1336 go dh.transitionMap.Handle(ctx, GrpcDisconnected)
1337 return nil
Girish Gowdru0c588b22019-04-23 23:24:56 -04001338 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301339
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001341
1342 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001343 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001344 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001345
1346 go startHeartbeatCheck(ctx, dh)
1347
cuilin20187b2a8c32019-03-26 19:52:28 -07001348 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301349}
1350
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001351func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001352 var err error
1353 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001354
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001355 if dh.flowMgr != nil {
1356 dh.StopAllFlowRoutines(ctx)
1357 }
1358
1359 dh.CloseKVClient(ctx)
1360
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001361 if err != nil {
1362 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1363 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001364 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1365 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301366 // If collector go routine is active, wait for it to stop
1367 dh.lockDevice.RLock()
1368 if dh.isCollectorActive {
1369 dh.lockDevice.RUnlock()
1370 dh.collectorWaitGroup.Wait()
1371 } else {
1372 dh.lockDevice.RUnlock()
1373 }
yasin saplid0566272021-12-21 09:10:30 +00001374 // +1 is for NNI
1375 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1376 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001377 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001378 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1379 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1380 // There is only one NNI manager since multiple NNI is not supported for now
1381 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001382 // Instantiate resource manager
1383 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 -07001384 return olterrors.ErrResourceManagerInstantiating
1385 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001386 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001387 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1388 // the KV store to manage mcast group data. Provide the first instance (0th index)
1389 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1390 return olterrors.ErrGroupManagerInstantiating
1391 }
yasin saplid0566272021-12-21 09:10:30 +00001392 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001393 // Instantiate flow manager
1394 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301395 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001396 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1397 } else {
1398 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001399 }
1400 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001401 /* TODO: Instantiate Alarm , stats , BW managers */
1402 /* Instantiating Event Manager to handle Alarms and KPIs */
1403 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1404
1405 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001406 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001407
1408 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001409}
1410
Neha Sharma96b7bf22020-06-15 10:37:32 +00001411func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001412 var err error
1413 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301414 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001415
bseenivaa1622112025-12-11 18:24:02 +05301416 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1417 deviceInfo, err = dh.Client.GetDeviceInfo(subCtx, new(oop.Empty))
1418 cancel()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001419
1420 if err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301421 return nil, olterrors.NewErrCommunication("get-device-info-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001422 }
1423 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001424 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001425 }
1426
Neha Sharma96b7bf22020-06-15 10:37:32 +00001427 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001428 dh.device.Root = true
1429 dh.device.Vendor = deviceInfo.Vendor
1430 dh.device.Model = deviceInfo.Model
1431 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1432 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1433 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1434
1435 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001436 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001437 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301438 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001439 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001440 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001441 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001442 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001443 dh.device.MacAddress = genmac
1444 } else {
1445 dh.device.MacAddress = deviceInfo.DeviceId
1446 }
1447
1448 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001449 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001450 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001451 }
1452
1453 return deviceInfo, nil
1454}
1455
Neha Sharma96b7bf22020-06-15 10:37:32 +00001456func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301457 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001458
1459 defer func() {
1460 dh.lockDevice.Lock()
1461 dh.isCollectorActive = false
1462 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301463 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001464 }()
1465
1466 dh.lockDevice.Lock()
1467 dh.isCollectorActive = true
1468 dh.lockDevice.Unlock()
1469
Naga Manjunath7615e552019-10-11 22:35:47 +05301470 for {
1471 select {
1472 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301473 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301474 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001475 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001476
khenaidoo106c61a2021-08-11 18:05:46 -04001477 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001478 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001479 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001480 continue
1481 }
khenaidoo106c61a2021-08-11 18:05:46 -04001482 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301483 // NNI Stats
1484 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001485 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301486 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001487 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001488 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001489 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301490 }
1491 // PON Stats
1492 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001493 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301494 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1495 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001496 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001497 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301498 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001499 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001500
yasin sapli9e4c5092022-02-01 13:52:33 +00001501 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001502 if len(onuGemInfoLst) > 0 {
1503 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001504 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001505 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301506 }
1507 }
1508 }
1509}
1510
Mahir Gunyela2e68702022-12-07 00:00:42 -08001511// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301512func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001513 var dhCtx context.Context
Girish Gowdru0c588b22019-04-23 23:24:56 -04001514 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001515 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001516 dhCtx, dh.transitionHandlerCancel = context.WithCancel(context.Background())
1517 dh.transitionMap.Handle(dhCtx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301518
1519 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001520 cgClient, err := dh.coreClient.GetCoreServiceClient()
1521 if err != nil {
1522 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1523 return
1524 }
1525
1526 // Now, set the initial PM configuration for that device
1527 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001528 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301529 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301530}
1531
Mahir Gunyela2e68702022-12-07 00:00:42 -08001532// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001533func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1534 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001535 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301536 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001537 HwDesc: "open_pon",
1538 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001539 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001540 },
1541 SwitchFeatures: &of.OfpSwitchFeatures{
1542 NBuffers: 256,
1543 NTables: 2,
1544 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1545 of.OfpCapabilities_OFPC_TABLE_STATS |
1546 of.OfpCapabilities_OFPC_PORT_STATS |
1547 of.OfpCapabilities_OFPC_GROUP_STATS),
1548 },
1549 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301550}
1551
khenaidoo106c61a2021-08-11 18:05:46 -04001552// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001553func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001554 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001555 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001556 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001557 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001558 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1559 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()
1560 }
khenaidoo106c61a2021-08-11 18:05:46 -04001561 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001562}
1563
Neha Sharma96b7bf22020-06-15 10:37:32 +00001564func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001565 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 -07001566 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001567 var deviceID string
1568 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001569 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001570
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001571 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001572 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001573 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 -07001574 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1575 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001576
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001577 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301578
1579 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001580 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 -07001581 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001582
khenaidoodc2116e2021-10-19 17:33:19 -04001583 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001584 ParentId: dh.device.Id,
1585 OnuId: omciInd.OnuId,
1586 ParentPortNo: ponPort,
1587 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001588 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301589 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001590 "intf-id": omciInd.IntfId,
1591 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001592 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001593 deviceType = onuDevice.Type
1594 deviceID = onuDevice.Id
1595 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001596 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301597 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001598 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001599 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301600 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001601 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 +05301602 deviceType = onuInCache.(*OnuDevice).deviceType
1603 deviceID = onuInCache.(*OnuDevice).deviceID
1604 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001605 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001606 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001607
khenaidoodc2116e2021-10-19 17:33:19 -04001608 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001609 ParentDeviceId: proxyDeviceID,
1610 ChildDeviceId: deviceID,
1611 Message: omciInd.Pkt,
1612 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301613 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001614 "source": dh.openOLT.config.AdapterEndpoint,
1615 "device-type": deviceType,
1616 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001618 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001619 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001620 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301621}
1622
khenaidoo106c61a2021-08-11 18:05:46 -04001623// //ProcessInterAdapterMessage sends the proxied messages to the target device
1624// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1625// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001626// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001627// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001628// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001629// return dh.handleInterAdapterOmciMsg(ctx, msg)
1630// }
1631// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1632// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001633
kesavandb9f54fd2021-11-25 20:08:04 +05301634// ProxyOmciRequests sends the proxied OMCI message to the target device
1635func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301636 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1637 return status.Error(codes.Unavailable, "OLT unreachable")
1638 }
kesavandb9f54fd2021-11-25 20:08:04 +05301639 if omciMsgs.GetProxyAddress() == nil {
1640 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1641 if err != nil {
1642 return olterrors.NewErrNotFound("onu", log.Fields{
1643 "parent-device-id": dh.device.Id,
1644 "child-device-id": omciMsgs.ChildDeviceId}, err)
1645 }
1646 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1647 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, 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 } else {
1653 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1654 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1655 return olterrors.NewErrCommunication("send-failed", log.Fields{
1656 "parent-device-id": dh.device.Id,
1657 "child-device-id": omciMsgs.ChildDeviceId}, err)
1658 }
1659 }
1660 return nil
1661}
1662
1663func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1664 var intfID uint32
1665 var onuID uint32
1666 var connectStatus common.ConnectStatus_Types
1667 if onuDevice != nil {
1668 intfID = onuDevice.ProxyAddress.GetChannelId()
1669 onuID = onuDevice.ProxyAddress.GetOnuId()
1670 connectStatus = onuDevice.ConnectStatus
1671 } else {
1672 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1673 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1674 connectStatus = omciMsgs.GetConnectStatus()
1675 }
1676 if connectStatus != voltha.ConnectStatus_REACHABLE {
1677 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1678
1679 return olterrors.NewErrCommunication("unreachable", log.Fields{
1680 "intf-id": intfID,
1681 "onu-id": onuID}, nil)
1682 }
1683
1684 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1685 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1686
1687 onuSecOmciMsgList := omciMsgs.GetMessages()
1688
1689 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301690 var omciMessage *oop.OmciMsg
1691 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1692 hex.Encode(hexPkt, onuSecOmciMsg)
1693 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1694
1695 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1696 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1697 //https://jira.opencord.org/browse/VOL-4604
1698 transid := extractOmciTransactionID(onuSecOmciMsg)
1699 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1700 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1701
bseenivaa1622112025-12-11 18:24:02 +05301702 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1703 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1704 cancel()
kesavandb9f54fd2021-11-25 20:08:04 +05301705 if err != nil {
1706 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1707 "intf-id": intfID,
1708 "onu-id": onuID,
1709 "message": omciMessage}, err)
1710 }
1711 }
1712 return nil
1713}
1714
khenaidoo106c61a2021-08-11 18:05:46 -04001715// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001716func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001717 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 -07001718
Akash Reddy Kankanala7b4d57e2026-01-26 23:18:18 +05301719 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) || DeviceState(dh.device.OperStatus) != DeviceState(voltha.OperStatus_ACTIVE) {
1720 return status.Error(codes.Unavailable, "OLT-is-unreachable-or-not-active")
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301721 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001722 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001723 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001724 if err != nil {
1725 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001726 "parent-device-id": dh.device.Id,
1727 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001728 }
khenaidoo106c61a2021-08-11 18:05:46 -04001729 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1730 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, 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)
cuilin20187b2a8c32019-03-26 19:52:28 -07001734 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001735 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001736 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1737 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001738 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001739 "parent-device-id": dh.device.Id,
1740 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001741 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001742 }
1743 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301744}
1745
khenaidoodc2116e2021-10-19 17:33:19 -04001746func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001747 var intfID uint32
1748 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001749 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001750 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001751 intfID = onuDevice.ProxyAddress.GetChannelId()
1752 onuID = onuDevice.ProxyAddress.GetOnuId()
1753 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001754 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001755 intfID = omciMsg.GetProxyAddress().GetChannelId()
1756 onuID = omciMsg.GetProxyAddress().GetOnuId()
1757 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001758 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001759 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760 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 -08001761
Thomas Lee S94109f12020-03-03 16:39:29 +05301762 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001763 "intf-id": intfID,
1764 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001765 }
1766
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001767 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1768 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301769 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001770 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001771 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1772 hex.Encode(hexPkt, omciMsg.Message)
1773 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1774
1775 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1776 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1777 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001778 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001779 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001780
bseenivaa1622112025-12-11 18:24:02 +05301781 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1782 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1783 cancel()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001784 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301785 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001786 "intf-id": intfID,
1787 "onu-id": onuID,
1788 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001789 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001790 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001791}
1792
David K. Bainbridge794735f2020-02-11 21:01:37 -08001793func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301794 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 +00001795 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001796 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001797 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001798 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301799 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
bseenivaa1622112025-12-11 18:24:02 +05301800 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1801 defer cancel()
1802 if _, err := dh.Client.ActivateOnu(subCtx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001803 st, _ := status.FromError(err)
1804 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001805 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 -04001806 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301807 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001808 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001809 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001811 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001812 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001813}
1814
Mahir Gunyela2e68702022-12-07 00:00:42 -08001815// getChildDevice function can be used in general to get child device, if not found in cache the function will
1816// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301817func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1818 var InCacheOnuDev *OnuDevice
1819 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1820 if onuInCache.(*OnuDevice).serialNumber == sn {
1821 InCacheOnuDev = onuInCache.(*OnuDevice)
1822 return false
1823 }
1824 return true
1825 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301826 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301827 if InCacheOnuDev != nil {
1828 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1829 return InCacheOnuDev
1830 }
1831 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1832 ParentId: dh.device.Id,
1833 SerialNumber: sn,
1834 ParentPortNo: parentPortNo,
1835 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301836 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301837 if onuDevice == nil {
1838 return nil
1839 }
1840 onuID := onuDevice.ProxyAddress.OnuId
1841 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1842 onuKey := dh.formOnuKey(intfID, onuID)
1843
1844 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1845 dh.onus.Store(onuKey, onuDev)
1846 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1847 return onuDev
1848}
1849
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301850// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1851// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301852func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001853 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301854 // 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 +05301855 // 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 +05301856 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
balaji.nagarajan90c15742026-01-30 10:08:24 +05301857 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301858 ParentId: dh.device.Id,
1859 SerialNumber: sn,
1860 ParentPortNo: parentPortNo,
1861 })
balaji.nagarajan90c15742026-01-30 10:08:24 +05301862 if err != nil {
1863 if e, ok := status.FromError(err); ok {
1864 switch e.Code() {
1865 case codes.NotFound:
1866 return false, nil
1867 default:
1868 logger.Errorw(ctx, "Unexpected error code while fetching device from core", log.Fields{"sn": sn, "error": err})
1869 return false, err
1870 }
1871 }
1872 }
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301873 if onuDevice != nil {
1874 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1875 return true, nil
1876 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05301877 logger.Debugw(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301878
1879 return false, nil
1880 } else {
1881 tpInstExists := false
1882 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301883 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1884 if onuDev != nil {
1885 var onuGemInfo *rsrcMgr.OnuGemInfo
1886 var err error
1887 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1888 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1889 return false, err
1890 }
1891 if onuGemInfo != nil {
1892 for _, uni := range onuGemInfo.UniPorts {
1893 uniID := plt.UniIDFromPortNum(uni)
1894 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1895 if len(tpIDs) != 0 {
1896 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1897 tpInstExists = true
1898 break
1899 }
1900 }
1901 }
1902 }
1903 return tpInstExists, nil
1904 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301905}
1906
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001907// processDiscONULOSClear clears the LOS Alarm if it's needed
1908func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301909 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001910 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301911
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001912 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1913 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1914 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1915 OnuLosRaise event sent for it */
1916 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1917 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1918 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1919 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1920 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1921 "currentIntfId": onuDiscInd.GetIntfId()})
1922 // TODO:: Should we need to ignore raising OnuLosClear event
1923 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301924 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001925 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1926 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1927 alarmInd.LosStatus = statusCheckOff
1928 go func() {
1929 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1930 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1931 }
1932 }()
1933 // stop iterating
1934 return false
1935 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301936 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001937 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301938}
1939
bseeniva43b5a912025-06-05 12:48:15 +05301940func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1941 if err != nil || tpInstExists {
1942 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1943 } else {
1944 // once the function completes set the value to false so that
1945 // we know the processing has inProcess.
1946 // Note that this is done after checking if we are already processing
1947 // to avoid changing the value from a different thread
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05301948 logger.Debugw(ctx, "onu-processing-completed", log.Fields{"sn": sn})
bseeniva43b5a912025-06-05 12:48:15 +05301949 dh.discOnus.Store(sn, false)
1950 }
1951}
1952
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301953func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301954 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301955 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301956
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301957 channelID := onuDiscInd.GetIntfId()
1958 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1959
1960 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301961 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301962 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301963 }()
1964
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301965 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1966
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301967 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1968 if !dh.cfg.ForceOnuDiscIndProcessing {
1969 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1970 if error != nil {
1971 return error
1972 }
1973 if tpInstExists {
1974 // ignore the discovery if tpinstance is present.
1975 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1976 return nil
1977 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001978 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001979 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1980
1981 // if the ONU existed, handle the LOS Alarm
1982 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001983 if inProcess.(bool) {
1984 // if we're currently processing the ONU on a different thread, do nothing
1985 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1986 return nil
1987 }
1988 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1989 // then continue processing it
1990 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1991
1992 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001993 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301994 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001995 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001996
1997 // check the ONU is already know to the OLT
1998 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301999 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002000 ParentId: dh.device.Id,
2001 SerialNumber: sn,
2002 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08002003
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302004 if error != nil {
2005 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
2006 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002007 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 -08002008 switch e.Code() {
balaji.nagarajan90c15742026-01-30 10:08:24 +05302009 case codes.Internal, codes.NotFound:
Matteo Scandolo945e4012019-12-12 14:16:11 -08002010 // this probably means NOT FOUND, so just create a new device
2011 onuDevice = nil
2012 case codes.DeadlineExceeded:
2013 // if the call times out, cleanup and exit
2014 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302015 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
2016 return error
balaji.nagarajan90c15742026-01-30 10:08:24 +05302017 default:
2018 //any other rpc errors
2019 dh.discOnus.Delete(sn)
2020 error = olterrors.NewErrAdapter("unexpected error code while fetching device from core", log.Fields{"device-id": dh.device.Id, "sn": sn}, error)
2021 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002022 }
2023 }
2024 }
2025
2026 if onuDevice == nil {
2027 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00002028 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002029 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04002030 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302031 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002032 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002033
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302034 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002035 // if we can't create an ID in resource manager,
2036 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08002037 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302038
2039 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002040 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302041 "serial-number": sn}, error)
2042 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002043 }
2044
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302045 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04002046 ParentId: dh.device.Id,
2047 ParentPortNo: parentPortNo,
2048 ChannelId: channelID,
2049 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
2050 SerialNumber: sn,
2051 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302052 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002053 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00002054 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 +05302055
2056 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002057 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302058 "serial-number": sn}, error)
2059 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002060 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302061 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 +05302062 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2063 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2064 "onu-id": onuID,
2065 "device-id": dh.device.Id,
2066 "serial-number": sn}, error)
2067 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002068 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302069 logger.Debugw(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302070 log.Fields{"onuDevice": onuDevice,
2071 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002072 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302073 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002074 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002075
khenaidoo106c61a2021-08-11 18:05:46 -04002076 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2077 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302078 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002079 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302080 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302081 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2082 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002083 }
2084
Matteo Scandolo945e4012019-12-12 14:16:11 -08002085 // we can now use the existing ONU Id
2086 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302087 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002088 //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 +00002089 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002090 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302091 "intfId": onuDiscInd.GetIntfId(),
2092 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002093 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002094
khenaidoo106c61a2021-08-11 18:05:46 -04002095 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302096 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002097 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302098 log.Fields{"onu": onuDev,
2099 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002100
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302101 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002102 DeviceId: onuDevice.Id,
2103 ParentDeviceId: dh.device.Id,
2104 OperStatus: common.OperStatus_DISCOVERED,
2105 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302106 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302107 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002108 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302109 "serial-number": sn}, error)
2110 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002111 }
khenaidoo106c61a2021-08-11 18:05:46 -04002112
Neha Sharma96b7bf22020-06-15 10:37:32 +00002113 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302114 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302115 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002116 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302117 "serial-number": sn}, error)
2118 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002119 }
2120 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002121}
2122
Mahir Gunyelb0046752021-02-26 13:51:05 -08002123func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002124 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002125 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002126 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002127 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302129 log.Fields{"onuId": onuInd.OnuId,
2130 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302131 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002132 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002133 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002134 errFields := log.Fields{"device-id": dh.device.Id}
2135
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302136 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302137 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002138 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002139 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002140 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002141 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302142 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002143 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002144 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002145 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002146 errFields["onu-id"] = onuInd.OnuId
2147 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002148 }
khenaidoodc2116e2021-10-19 17:33:19 -04002149 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002150 ParentId: dh.device.Id,
2151 SerialNumber: serialNumber,
2152 OnuId: onuInd.OnuId,
2153 ParentPortNo: ponPort,
2154 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002155 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002156
David K. Bainbridge794735f2020-02-11 21:01:37 -08002157 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002158 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002159 }
2160
David K. Bainbridge794735f2020-02-11 21:01:37 -08002161 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002162 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002163 "previousIntfId": onuDevice.ParentPortNo,
2164 "currentIntfId": ponPort})
2165 }
2166
2167 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302169 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2170 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302171 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002172 }
2173 if !foundInCache {
2174 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002175 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 -08002176 }
kesavand7cf3a052020-08-28 12:49:18 +05302177 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002178 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002179 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302180 }
2181 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002183 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002184 }
2185 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002186}
2187
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002189 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 -07002190 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2191 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2192 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2193 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002194 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002195 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2196 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002198 onuInd.OperState = "down"
2199 }
2200 }
2201
David K. Bainbridge794735f2020-02-11 21:01:37 -08002202 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002203 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002204 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 -04002205
khenaidoodc2116e2021-10-19 17:33:19 -04002206 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002207 DeviceId: onuDevice.Id,
2208 OnuIndication: onuInd,
2209 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002210 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302211 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002212 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002213 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002214 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002215 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002216 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002217 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002218 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002219 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002220 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002221}
2222
cuilin20187b2a8c32019-03-26 19:52:28 -07002223func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2224 if serialNum != nil {
2225 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002226 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002227 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002228}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002229func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2230 decodedStr, err := hex.DecodeString(serialNum[4:])
2231 if err != nil {
2232 return nil, err
2233 }
2234 return &oop.SerialNumber{
2235 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002236 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002237 }, nil
2238}
cuilin20187b2a8c32019-03-26 19:52:28 -07002239
2240func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002241 if len(vendorSpecific) > 3 {
2242 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2243 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2244 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2245 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2246 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2247 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2248 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2249 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2250 return tmp
2251 }
2252 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002253}
2254
Mahir Gunyela2e68702022-12-07 00:00:42 -08002255// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002256func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302257 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002258}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002259
Mahir Gunyela2e68702022-12-07 00:00:42 -08002260// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002261func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2262 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302263 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002264 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302265 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002266
khenaidoodc2116e2021-10-19 17:33:19 -04002267 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002268 ParentId: dh.device.Id,
2269 OnuId: onuID,
2270 ParentPortNo: parentPort,
2271 })
2272
Girish Gowdru0c588b22019-04-23 23:24:56 -04002273 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002274 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002275 "intf-id": parentPort,
2276 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002278 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 -08002279 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302280}
2281
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002282// SendPacketInToCore sends packet-in to core
2283// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2284// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002285func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002286 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002287 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002288 "port": logicalPort,
2289 "packet": hex.EncodeToString(packetPayload),
2290 "device-id": dh.device.Id,
2291 })
2292 }
khenaidoo106c61a2021-08-11 18:05:46 -04002293
khenaidoodc2116e2021-10-19 17:33:19 -04002294 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002295 DeviceId: dh.device.Id,
2296 Port: logicalPort,
2297 Packet: packetPayload,
2298 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302299 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002300 "source": "adapter",
2301 "destination": "core",
2302 "device-id": dh.device.Id,
2303 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002304 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002305 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002306 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002307 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002308 "packet": hex.EncodeToString(packetPayload),
2309 "device-id": dh.device.Id,
2310 })
2311 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002312 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002313}
2314
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002315// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002317 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002318
2319 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2320 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002321 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002322 }
2323
Kent Hagermane6ff1012020-07-14 15:07:53 -04002324 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002325 metrics := dh.metrics.GetSubscriberMetrics()
2326 for _, m := range pmConfigs.Metrics {
2327 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002328 }
2329 }
2330}
2331
khenaidoodc2116e2021-10-19 17:33:19 -04002332func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002333 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002334 var errorsList []error
2335
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002336 if dh.getDeviceDeletionInProgressFlag() {
2337 // The device itself is going to be reset as part of deletion. So nothing to be done.
2338 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2339 return nil
2340 }
2341
Girish Gowdru0c588b22019-04-23 23:24:56 -04002342 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002343 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302344 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002345
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302347 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002348 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302349 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002350 if flow_utils.HasGroup(flow) {
2351 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2352 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002353 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2354 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2355 } else {
2356 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2357 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002358 }
Girish Gowdracefae192020-03-19 18:14:10 -07002359 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002360 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302361 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002362 logger.Warnw(ctx, "flow-to-remove-not-found",
2363 log.Fields{
2364 "ponIf": intfID,
2365 "flowToRemove": flow,
2366 "error": err,
2367 })
2368 } else {
2369 errorsList = append(errorsList, err)
2370 }
Girish Gowdracefae192020-03-19 18:14:10 -07002371 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002372 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302373
2374 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302375 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302377 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002378 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302379 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002380 if flow_utils.HasGroup(flow) {
2381 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2382 } else {
yasin saplid0566272021-12-21 09:10:30 +00002383 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002384 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2385 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2386 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2387 } else {
yasin saplid0566272021-12-21 09:10:30 +00002388 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002389 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002390 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002391 if err != nil {
2392 errorsList = append(errorsList, err)
2393 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302394 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002395 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002396
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002397 return errorsList
2398}
2399
2400func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2401 var err error
2402 var errorsList []error
2403
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002404 if dh.getDeviceDeletionInProgressFlag() {
2405 // The device itself is going to be reset as part of deletion. So nothing to be done.
2406 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2407 return nil
2408 }
2409
Girish Gowdracefae192020-03-19 18:14:10 -07002410 // 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 +00002411 if groups != nil {
2412 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002413 // err = dh.groupMgr.AddGroup(ctx, group)
2414 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002415 if err != nil {
2416 errorsList = append(errorsList, err)
2417 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002418 }
2419 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002420 // err = dh.groupMgr.ModifyGroup(ctx, group)
2421 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002422 if err != nil {
2423 errorsList = append(errorsList, err)
2424 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002425 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002426 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002427 // err = dh.groupMgr.DeleteGroup(ctx, group)
2428 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002429 if err != nil {
2430 errorsList = append(errorsList, err)
2431 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002432 }
2433 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002434
2435 return errorsList
2436}
2437
Mahir Gunyela2e68702022-12-07 00:00:42 -08002438// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002439func (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 -07002440 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002441
2442 if dh.getDeviceDeletionInProgressFlag() {
2443 // The device itself is going to be reset as part of deletion. So nothing to be done.
2444 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2445 return nil
2446 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302447 if dh.transitionMap.currentDeviceState != deviceStateUp {
2448 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2449 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2450 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002451 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2452 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2453 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002454 if len(errorsList) > 0 {
2455 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2456 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002457 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002458 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302459}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002460
Mahir Gunyela2e68702022-12-07 00:00:42 -08002461// DisableDevice disables the given device
2462// It marks the following for the given device:
2463// Device-Handler Admin-State : down
2464// Device Port-State: UNKNOWN
2465// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002466func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002467 /* On device disable ,admin state update has to be done prior sending request to agent since
2468 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002469 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302470 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2471 if _, err := dh.Client.DisableOlt(subCtx, new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002472 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302473 cancel()
Girish Kumarf26e4882020-03-05 06:49:10 +00002474 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002475 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002476 }
bseenivaa1622112025-12-11 18:24:02 +05302477 cancel()
Chaitrashree G S44124192019-08-07 20:21:36 -04002478 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002479 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002480 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002481 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302482
2483 dh.discOnus = sync.Map{}
2484 dh.onus = sync.Map{}
2485
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002486 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302487 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002488 if dh.isCollectorActive {
2489 dh.stopCollector <- true
2490 }
2491 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302492
Neha Sharma96b7bf22020-06-15 10:37:32 +00002493 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002494 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302495 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302496 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002497
kdarapu1afeceb2020-02-12 01:38:09 -05002498 // 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 -04002499 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002500 DeviceId: cloned.Id,
2501 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2502 OperStatus: voltha.OperStatus_UNKNOWN,
2503 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002504 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002505 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002506 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002507 return nil
2508}
2509
Neha Sharma96b7bf22020-06-15 10:37:32 +00002510func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002511 // Update onu state as unreachable in onu adapter
2512 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302513 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002514
Akash Kankanala041a2122024-10-16 15:49:22 +05302515 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002516 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002517 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002518 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 -04002519 }
2520 if onuDevices != nil {
2521 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002522 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002523 DeviceId: onuDevice.Id,
2524 OnuIndication: &onuInd,
2525 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002526 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002527 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002528 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002529 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002530 }
2531 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002532}
2533
Mahir Gunyela2e68702022-12-07 00:00:42 -08002534// ReenableDevice re-enables the olt device after disable
2535// It marks the following for the given device:
2536// Device-Handler Admin-State : up
2537// Device Port-State: ACTIVE
2538// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002539func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302540 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302541 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2542 if _, err := dh.Client.ReenableOlt(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302543 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302544 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302545 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2546 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302547 }
bseenivaa1622112025-12-11 18:24:02 +05302548 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302549 } else {
2550 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 +05302551 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002552 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002553
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002554 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002555 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002556 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002557 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002558 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2559 } else {
2560 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2561 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2562 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002563 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002564 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302565 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002566 device.OperStatus = voltha.OperStatus_ACTIVE
2567 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302568 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002569 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002570 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002571 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002572
khenaidoodc2116e2021-10-19 17:33:19 -04002573 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002574 DeviceId: device.Id,
2575 OperStatus: device.OperStatus,
2576 ConnStatus: device.ConnectStatus,
2577 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302578 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002579 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002580 "connect-status": device.ConnectStatus,
2581 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002582 }
kesavand39e0aa32020-01-28 20:58:50 -05002583
Neha Sharma96b7bf22020-06-15 10:37:32 +00002584 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002585
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002586 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002587}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002588
npujarec5762e2020-01-01 14:08:48 +05302589func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002590 var uniID uint32
2591 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002592 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302593 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002594 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002595 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002596 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002597 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2598 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2599 } else {
2600 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2601 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002602 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002603 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002604 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002605 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002606 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002607 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002608 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002609 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002610 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002611 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002612 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002613 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002614 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002615 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002616 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002617 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302618 }
yasin saplibddc2d72022-02-08 13:10:17 +00002619 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2620 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002621 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002622 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302623 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002624 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002625 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002626 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 -03002627 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002628 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002629 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002630 if len(errs) > 0 {
2631 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2632 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2633 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002634 return nil
2635}
2636
Devmalya Paul495b94a2019-08-27 19:42:00 -04002637// 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 +05302638func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002639 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002640 /* Clear the KV store data associated with the all the UNI ports
2641 This clears up flow data and also resource map data for various
2642 other pon resources like alloc_id and gemport_id
2643 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002644
Abhay Kumarb87ac882025-10-30 09:55:07 +00002645 if dh.getDeviceDeletionInProgressFlag() {
2646 logger.Errorw(ctx, "cannot complete operation as device deletion is in progress", log.Fields{"device-id": dh.device.Id})
2647 return olterrors.NewErrAdapter(fmt.Errorf("cannot complete operation as device deletion is in progress").Error(), log.Fields{"device-id": dh.device.Id}, nil)
2648 }
2649
Girish Gowdra950326e2021-11-05 12:43:24 -07002650 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002651 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002652
Himani Chawla49a5d562020-11-25 11:53:44 +05302653 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002654 // Stop the Stats collector
2655 if dh.isCollectorActive {
2656 dh.stopCollector <- true
2657 }
2658 // stop the heartbeat check routine
2659 if dh.isHeartbeatCheckActive {
2660 dh.stopHeartbeatCheck <- true
2661 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302662 // Stop the read indication only if it the routine is active
2663 if dh.isReadIndicationRoutineActive {
2664 dh.stopIndications <- true
2665 }
2666 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302667
2668 err := dh.cleanupDeviceResources(ctx)
2669 if err != nil {
2670 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 +05302671 dh.setDeviceDeletionInProgressFlag(false)
2672 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 +05302673 } else {
2674 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2675 }
2676
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002677 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302678 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002679 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302680 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2681 if _, err = dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002682 go func() {
2683 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302684 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2685 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002686 }
2687 }()
2688 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002689 }
bseenivaa1622112025-12-11 18:24:02 +05302690 cancel()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002691 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002692 // There is no need to update the core about operation status and connection status of the OLT.
2693 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2694 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2695 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002696
khenaidoo7eb2d672021-10-22 19:08:50 -04002697 // Stop the adapter grpc clients for that parent device
2698 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002699 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002700}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002701
2702// StopAllFlowRoutines stops all flow routines
2703func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2704 var wg sync.WaitGroup
2705 wg.Add(1) // for the mcast routine below to finish
2706 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2707 for _, flMgr := range dh.flowMgr {
2708 if flMgr != nil {
2709 wg.Add(1) // for the flow handler routine below to finish
2710 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2711 }
2712 }
2713 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2714 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2715 } else {
2716 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2717 }
2718}
2719
Gustavo Silva41af9122022-10-11 11:05:13 -03002720func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2721 var errs []error
Abhay Kumarb87ac882025-10-30 09:55:07 +00002722 if dh.resourceMgr != nil && dh.totalPonPorts > 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302723 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002724 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
balaji.nagarajanfa561fc2026-02-04 09:34:33 +05302725 if dh.resourceMgr[ponPort] == nil {
2726 logger.Warnw(ctx, "resource manager for ponPort is nil", log.Fields{"ponPort": ponPort})
2727 continue
2728 }
yasin sapli9e4c5092022-02-01 13:52:33 +00002729 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002730 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002731 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002732 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2733 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302734 }
2735 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002736 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2737 errs = append(errs, err)
2738 }
2739 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2740 errs = append(errs, err)
2741 }
2742 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2743 errs = append(errs, err)
2744 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002745 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002746 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002747 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002748 }
balaji.nagarajanfa561fc2026-02-04 09:34:33 +05302749 // Clean up NNI manager's data
2750 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2751 errs = append(errs, err)
2752 }
2753 } else {
2754 logger.Errorw(ctx, "resource manager empty, ignoring resource cleanup", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002755 }
A R Karthick1f85b802019-10-11 05:06:05 +00002756
balaji.nagarajan2e572c42026-01-27 15:09:39 +05302757 if len(errs) == 0 {
2758 // Take one final sweep at cleaning up KV store for the OLT device
2759 // Clean everything at <base-path-prefix>/openolt/<device-id>
2760 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2761 errs = append(errs, err)
2762 }
2763 logger.Debugw(ctx, "lockDevice for KVStore close client", log.Fields{"deviceID": dh.device.Id})
2764 dh.CloseKVClient(ctx)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002765 }
2766
Devmalya Paul495b94a2019-08-27 19:42:00 -04002767 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302768 dh.onus.Range(func(key interface{}, value interface{}) bool {
2769 dh.onus.Delete(key)
2770 return true
2771 })
2772
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002773 /*Delete discovered ONU map for the device*/
2774 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2775 dh.discOnus.Delete(key)
2776 return true
2777 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002778 if len(errs) > 0 {
2779 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2780 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2781 }
2782 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002783}
2784
Mahir Gunyela2e68702022-12-07 00:00:42 -08002785// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002786func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302787 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302788 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2789 defer cancel()
2790 if _, err := dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302791 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2792 }
2793 } else {
2794 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 -04002795 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302796
Neha Sharma96b7bf22020-06-15 10:37:32 +00002797 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002798 return nil
2799}
2800
David K. Bainbridge794735f2020-02-11 21:01:37 -08002801func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002802 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002803 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002804 "packet-indication": *packetIn,
2805 "device-id": dh.device.Id,
2806 "packet": hex.EncodeToString(packetIn.Pkt),
2807 })
2808 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002809 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2810 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2811 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002812 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002813 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002814 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002815 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002816 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002817 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002818 "logical-port-num": logicalPortNum,
2819 "device-id": dh.device.Id,
2820 "packet": hex.EncodeToString(packetIn.Pkt),
2821 })
2822 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002823
khenaidoodc2116e2021-10-19 17:33:19 -04002824 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002825 DeviceId: dh.device.Id,
2826 Port: logicalPortNum,
2827 Packet: packetIn.Pkt,
2828 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302829 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002830 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302831 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002832 "device-id": dh.device.Id,
2833 "packet": hex.EncodeToString(packetIn.Pkt),
2834 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002835 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002836
Matteo Scandolo92186242020-06-12 10:54:18 -07002837 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002838 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002839 "packet": hex.EncodeToString(packetIn.Pkt),
2840 "device-id": dh.device.Id,
2841 })
2842 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002843 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002844}
2845
Mahir Gunyela2e68702022-12-07 00:00:42 -08002846// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2847func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2848 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2849 if err != nil {
2850 return olterrors.NewErrInvalidValue(log.Fields{
2851 "egress-nni-port": egressPortNo,
2852 "device-id": dh.device.Id,
2853 }, err)
2854 }
2855 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2856
2857 if logger.V(log.DebugLevel) {
2858 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2859 "uplink-pkt": uplinkPkt,
2860 "packet": hex.EncodeToString(packet.Data),
2861 "device-id": dh.device.Id,
2862 })
2863 }
2864
bseenivaa1622112025-12-11 18:24:02 +05302865 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2866 defer cancel()
2867 if _, err := dh.Client.UplinkPacketOut(subCtx, &uplinkPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002868 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2869 "packet": hex.EncodeToString(packet.Data),
2870 "device-id": dh.device.Id,
2871 }, err)
2872 }
2873 return nil
2874}
2875
2876// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2877func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2878 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2879 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2880 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2881 // Do not packet-out lldp packets on uni port.
2882 // ONOS has no clue about uni/nni ports, it just packets out on all
2883 // available ports on the Logical Switch. It should not be interested
2884 // in the UNI links.
2885 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2886 "device-id": dh.device.Id,
2887 })
2888 return nil
2889 }
2890 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2891 if innerEthType == 0x8100 {
2892 // q-in-q 802.1ad or 802.1q double tagged packet.
2893 // slice out the outer tag.
2894 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2895 if logger.V(log.DebugLevel) {
2896 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2897 "packet-data": hex.EncodeToString(packet.Data),
2898 "device-id": dh.device.Id,
2899 })
2900 }
2901 }
2902 }
2903 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2904 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2905 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2906 var gemPortID uint32
2907 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2908 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2909 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2910 }
2911 if err != nil {
2912 // In this case the openolt agent will receive the gemPortID as 0.
2913 // The agent tries to retrieve the gemPortID in this case.
2914 // This may not always succeed at the agent and packetOut may fail.
2915 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2916 "intf-id": intfID,
2917 "onu-id": onuID,
2918 "uni-id": uniID,
2919 "packet": hex.EncodeToString(packet.Data),
2920 "device-id": dh.device.Id,
2921 "error": err,
2922 })
2923 }
2924
2925 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2926 if logger.V(log.DebugLevel) {
2927 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2928 "egress-port-no": egressPortNo,
2929 "intf-id": intfID,
2930 "onu-id": onuID,
2931 "uni-id": uniID,
2932 "gem-port-id": gemPortID,
2933 "packet": hex.EncodeToString(packet.Data),
2934 "device-id": dh.device.Id,
2935 })
2936 }
2937
bseenivaa1622112025-12-11 18:24:02 +05302938 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2939 defer cancel()
2940 if _, err := dh.Client.OnuPacketOut(subCtx, &onuPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002941 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2942 "source": "adapter",
2943 "destination": "onu",
2944 "egress-port-number": egressPortNo,
2945 "intf-id": intfID,
2946 "oni-id": onuID,
2947 "uni-id": uniID,
2948 "gem-port-id": gemPortID,
2949 "packet": hex.EncodeToString(packet.Data),
2950 "device-id": dh.device.Id,
2951 }, err)
2952 }
2953 return nil
2954}
2955
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002956// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002957func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002958 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002959 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002960 "device-id": dh.device.Id,
2961 "egress-port-no": egressPortNo,
2962 "pkt-length": len(packet.Data),
2963 "packet": hex.EncodeToString(packet.Data),
2964 })
2965 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002966
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002967 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002968 var err error
mgouda86543582025-10-29 20:58:16 +05302969 switch egressPortType {
2970 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002971 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302972 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002973 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302974 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002975 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302976 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002977 "egressPortType": egressPortType,
2978 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302979 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002980 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002981 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002982 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002983}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002985func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2986 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002987}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302988
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002989func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002990 defer func() {
2991 dh.lockDevice.Lock()
2992 dh.isHeartbeatCheckActive = false
2993 dh.lockDevice.Unlock()
2994 }()
2995
2996 dh.lockDevice.Lock()
2997 dh.isHeartbeatCheckActive = true
2998 dh.lockDevice.Unlock()
2999
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303000 // start the heartbeat check towards the OLT.
3001 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303002 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303003
3004 for {
3005 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
3006 select {
3007 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00003008 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003009 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003010 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303011 if timerCheck == nil {
3012 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003013 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303014 }
3015 } else {
3016 if timerCheck != nil {
3017 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003018 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303019 }
3020 timerCheck = nil
3021 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303022 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
3023 if dh.heartbeatSignature == 0 {
3024 // First time the signature will be 0, update the signture to DB when not found.
3025 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
3026 dh.heartbeatSignature = heartBeat.HeartbeatSignature
3027 }
3028 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
3029
3030 dh.lockDevice.RLock()
3031 // Stop the read indication only if it the routine is active
3032 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3033 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3034 // on next execution of the readIndication routine.
3035 if !dh.isReadIndicationRoutineActive {
3036 // Start reading indications
3037 go func() {
3038 if err = dh.readIndications(ctx); err != nil {
3039 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3040 }
3041 }()
3042 }
3043 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303044 } else {
3045 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
balaji.nagarajan2e572c42026-01-27 15:09:39 +05303046 dh.updateStateRebooted(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303047 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
3048 dh.heartbeatSignature = heartBeat.HeartbeatSignature
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303049 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303050 }
3051 cancel()
3052 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003053 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303054 return
3055 }
3056 }
3057}
3058
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003059func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04003060 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003061 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07003062 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3063 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3064 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3065 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3066 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003067 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07003068 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3069 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003070 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303071
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303072 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003073 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003074 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04003075 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04003076 DeviceId: dh.device.Id,
3077 OperStatus: voltha.OperStatus_UNKNOWN,
3078 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
3079 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003080 _ = 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 -04003081 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303082 /*
3083 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
3084 DeviceId: dh.device.Id,
3085 PortTypeFilter: 0,
3086 OperStatus: voltha.OperStatus_UNKNOWN,
3087 }); err != nil {
3088 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3089 }
3090 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003091
Akash Kankanala041a2122024-10-16 15:49:22 +05303092 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003093 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003094 cloned := proto.Clone(device).(*voltha.Device)
3095 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3096 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3097 dh.device = cloned // update local copy of the device
3098 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003099
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003100 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003101 // Stop the Stats collector
3102 if dh.isCollectorActive {
3103 dh.stopCollector <- true
3104 }
3105 // stop the heartbeat check routine
3106 if dh.isHeartbeatCheckActive {
3107 dh.stopHeartbeatCheck <- true
3108 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003109 // Stop the read indication only if it the routine is active
3110 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3111 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3112 // on next execution of the readIndication routine.
3113 if dh.isReadIndicationRoutineActive {
3114 dh.stopIndications <- true
3115 }
3116 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003117 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303118 }
3119}
kesavand39e0aa32020-01-28 20:58:50 -05003120
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303121func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3122 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3123 if err != nil || device == nil {
3124 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3125 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3126 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3127 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3128 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3129 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3130 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3131 return
3132 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303133 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003134 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303135
3136 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3137 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303138 // First, stop the read indication and heartbeat check routines to prevent any delay
3139 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303140 dh.lockDevice.RLock()
3141 // Stop the read indication only if it the routine is active
3142 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3143 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3144 // on next execution of the readIndication routine.
3145 if dh.isReadIndicationRoutineActive {
3146 dh.stopIndications <- true
3147 }
balaji.nagarajanc7503512026-02-04 09:47:43 +05303148
3149 // stop the heartbeat check routine
3150 if dh.isHeartbeatCheckActive {
3151 dh.stopHeartbeatCheck <- true
3152 }
3153
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303154 dh.lockDevice.RUnlock()
3155
bseenivad1c984b2025-01-09 12:54:44 +05303156 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3157 DeviceId: dh.device.Id,
3158 OperStatus: voltha.OperStatus_REBOOTED,
3159 ConnStatus: voltha.ConnectStatus_REACHABLE,
3160 }); err != nil {
3161 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3162 }
3163
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303164 //raise olt communication failure event
3165 raisedTs := time.Now().Unix()
3166 cloned := proto.Clone(device).(*voltha.Device)
3167 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3168 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3169 dh.device = cloned // update local copy of the device
3170 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3171
Gustavo Silva41af9122022-10-11 11:05:13 -03003172 if err := dh.cleanupDeviceResources(ctx); err != nil {
3173 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3174 } else {
3175 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3176 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003177
3178 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303179 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003180 if dh.isCollectorActive {
3181 dh.stopCollector <- true
3182 }
balaji.nagarajanc7503512026-02-04 09:47:43 +05303183
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003184 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303185
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003186 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303187
Akash Kankanala041a2122024-10-16 15:49:22 +05303188 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303189 dh.adapterPreviouslyConnected = false
3190 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303191 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3192 if err != nil || childDevices == nil {
3193 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3194 continue
3195 }
3196 if len(childDevices.Items) == 0 {
3197 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3198 break
3199 } else {
3200 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3201 time.Sleep(5 * time.Second)
3202 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303203 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303204 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003205 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303206 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3207 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303208}
3209
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303210// EnableOnuSerialNumber to enable onu serial number
3211func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3212 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3213 onuSerialNumber := device.SerialNumber
3214
3215 // fetch interfaceid from PortNo
3216 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3217
3218 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3219 if err != nil {
3220 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3221 log.Fields{
3222 "devicer-id": dh.device.Id,
3223 "serial-number": onuSerialNumber}, err).Log()
3224 }
3225
3226 onuIntf := &oop.InterfaceOnuSerialNumber{
3227 IntfId: ponID,
3228 OnuSerialNumber: sn,
3229 }
3230 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3231
3232 if err != nil {
3233 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3234 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3235 "device-id": dh.device.Id,
3236 "onu-serial-number": onuSerialNumber}, err)
3237 }
3238 return nil
3239}
3240
3241// DisableOnuSerialNumber to disable onu serial number
3242func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3243 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3244 onuSerialNumber := device.SerialNumber
3245 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3246 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3247 if err != nil {
3248 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3249 log.Fields{
3250 "devicer-id": dh.device.Id,
3251 "serial-number": onuSerialNumber}, err).Log()
3252 }
3253
3254 onuIntf := &oop.InterfaceOnuSerialNumber{
3255 OnuSerialNumber: sn,
3256 IntfId: ponID,
3257 }
3258 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3259
3260 if err != nil {
3261 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3262 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3263 "device-id": dh.device.Id,
3264 "onu-serial-number": onuSerialNumber}, err)
3265 }
3266 return nil
3267}
3268
3269// EnableOnu to enable onu
3270func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3271 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3272 onuSerialNumber := device.SerialNumber
3273 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3274 if InCacheOnuDev == nil {
3275 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3276 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3277 "device-id": dh.device.Id,
3278 "onu-serial-number": onuSerialNumber}, nil)
3279 }
3280 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})
3281
3282 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3283 if err != nil {
3284 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3285 log.Fields{
3286 "device-id": dh.device.Id,
3287 "serial-number": onuSerialNumber}, err).Log()
3288 }
3289
3290 onuIntf := &oop.InterfaceOnuSerialNumber{
3291 OnuSerialNumber: sn,
3292 IntfId: InCacheOnuDev.intfID,
3293 }
3294 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3295 OnuId: InCacheOnuDev.onuID,
3296 IntfIdSerialNum: onuIntf,
3297 }
3298 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3299
3300 if err != nil {
3301 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3302 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3303 "olt-device-id": dh.device.Id,
3304 "onu-serial-number": onuSerialNumber}, err)
3305 }
3306 return nil
3307}
3308
3309// DisableOnu to disable onu
3310func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3311 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3312 onuSerialNumber := device.SerialNumber
3313 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3314 if InCacheOnuDev == nil {
3315 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3316 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3317 "device-id": dh.device.Id,
3318 "onu-serial-number": onuSerialNumber}, nil)
3319 }
3320 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})
3321
3322 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3323 if err != nil {
3324 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3325 log.Fields{
3326 "device-id": dh.device.Id,
3327 "serial-number": onuSerialNumber}, err).Log()
3328 }
3329
3330 onuIntf := &oop.InterfaceOnuSerialNumber{
3331 OnuSerialNumber: sn,
3332 IntfId: InCacheOnuDev.intfID,
3333 }
3334 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3335 OnuId: InCacheOnuDev.onuID,
3336 IntfIdSerialNum: onuIntf,
3337 }
3338 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3339
3340 if err != nil {
3341 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3342 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3343 "olt-device-id": dh.device.Id,
3344 "onu-serial-number": onuSerialNumber}, err)
3345 }
3346 return nil
3347}
3348
kesavand39e0aa32020-01-28 20:58:50 -05003349// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003350func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3351 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3352 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003353}
3354
3355// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003356func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3357 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3358 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003359}
3360
Mahir Gunyela2e68702022-12-07 00:00:42 -08003361// 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 +00003362func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3363 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003364 if port.GetType() == voltha.Port_ETHERNET_NNI {
3365 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003366 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303367 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303368 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003369 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003370 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003371 }
3372 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003373 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003374 ponIntf := &oop.Interface{IntfId: ponID}
3375 var operStatus voltha.OperStatus_Types
bseenivaa1622112025-12-11 18:24:02 +05303376 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
kesavand39e0aa32020-01-28 20:58:50 -05003377 if enablePort {
3378 operStatus = voltha.OperStatus_ACTIVE
bseenivaa1622112025-12-11 18:24:02 +05303379 out, err := dh.Client.EnablePonIf(subCtx, ponIntf)
3380 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003381 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303382 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003383 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003384 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003385 }
3386 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003387 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003388 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003389 } else {
3390 operStatus = voltha.OperStatus_UNKNOWN
bseenivaa1622112025-12-11 18:24:02 +05303391 out, err := dh.Client.DisablePonIf(subCtx, ponIntf)
3392 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003393 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303394 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003395 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003396 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003397 }
3398 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003399 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003400 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003401 }
khenaidoodc2116e2021-10-19 17:33:19 -04003402 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003403 DeviceId: dh.device.Id,
3404 PortType: voltha.Port_PON_OLT,
3405 PortNo: port.PortNo,
3406 OperStatus: operStatus,
3407 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303408 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303409 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003410 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003411 }
3412 return nil
3413}
3414
Mahir Gunyela2e68702022-12-07 00:00:42 -08003415// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003416func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003417 // Disable the port and update the oper_port_status to core
3418 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003419 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003420 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003421 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303422 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303423 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003424 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003425 }
3426 }
3427 }
3428 return nil
3429}
3430
Mahir Gunyela2e68702022-12-07 00:00:42 -08003431// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003432func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3433 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3434 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003435 if port.Type == voltha.Port_ETHERNET_NNI {
3436 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003437 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003438 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003439 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003440 }
3441 }
3442 if port.Type == voltha.Port_PON_OLT {
3443 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003444 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003445 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003446 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003447 }
3448 }
3449 }
3450}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003451
3452// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003453func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003454 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003455 if dh.getDeviceDeletionInProgressFlag() {
3456 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3457 // will reboot, so everything will be reset on the pOLT too.
3458 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3459 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3460 return nil
3461 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303462
3463 if dh.transitionMap.currentDeviceState != deviceStateUp {
3464 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})
3465 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3466 }
3467
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003468 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003469 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003470
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003471 var sn *oop.SerialNumber
3472 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003473 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303474 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003475 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303476 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003477 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003478 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003479
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003480 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303481 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003482 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003483 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3484 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3485 "device-id": dh.device.Id,
3486 "intf-id": intfID,
3487 "onuID": onuID,
3488 "err": err})
3489 } else {
3490 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003491 // Delete flows from device before schedulers and queue
3492 // Clear flowids for gem cache.
3493 removedFlows := []uint64{}
3494 for _, gem := range onuGem.GemPorts {
3495 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3496 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303497 // multiple gem port can have the same flow id
3498 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003499 var alreadyRemoved bool
3500 for _, removedFlowID := range removedFlows {
3501 if removedFlowID == flowID {
3502 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3503 alreadyRemoved = true
3504 break
3505 }
3506 }
3507 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003508 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003509 removedFlows = appendUnique64bit(removedFlows, flowID)
3510 }
3511 }
3512 }
3513 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3514 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003515 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3516 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3517 "device-id": dh.device.Id,
3518 "onu-device": onu,
3519 "err": err})
3520 }
yasin saplibddc2d72022-02-08 13:10:17 +00003521 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003522 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3523 "intf-id": intfID,
3524 "onu-device": onu,
3525 "onu-gem": onuGem,
3526 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303527 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003528 }
3529 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003530 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003531
bseenivaa1622112025-12-11 18:24:02 +05303532 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003533 // Now clear the ONU on the OLT
bseenivaa1622112025-12-11 18:24:02 +05303534 if _, err := dh.Client.DeleteOnu(subCtx, onu); err != nil {
3535 cancel()
Thomas Lee S94109f12020-03-03 16:39:29 +05303536 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303537 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003538 "onu-id": onuID}, err).Log()
3539 }
bseenivaa1622112025-12-11 18:24:02 +05303540 cancel()
balaji.nagarajanbf44ce82026-01-27 08:59:36 +05303541
3542 //free resources only if the deleteonu is successful
3543 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
3544 dh.onus.Delete(onuKey)
3545 dh.discOnus.Delete(onuSn)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003546 return nil
3547}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003548func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3549 flow := &oop.Flow{FlowId: flowID}
3550 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3551 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3552 "device-id": dh.device.Id})
3553 } else {
3554 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3555 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3556 "device-id": dh.device.Id,
3557 "err": err})
3558 }
3559 }
3560}
Girish Gowdracefae192020-03-19 18:14:10 -07003561
3562func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003563 for _, field := range flow_utils.GetOfbFields(flow) {
3564 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003565 return field.GetPort()
3566 }
3567 }
3568 return InvalidPort
3569}
3570
3571func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003572 for _, action := range flow_utils.GetActions(flow) {
3573 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003574 if out := action.GetOutput(); out != nil {
3575 return out.GetPort()
3576 }
3577 }
3578 }
3579 return InvalidPort
3580}
3581
Girish Gowdracefae192020-03-19 18:14:10 -07003582func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3583 inPort := getInPortFromFlow(flow)
3584 outPort := getOutPortFromFlow(flow)
3585
3586 if inPort == InvalidPort || outPort == InvalidPort {
3587 return inPort, outPort
3588 }
3589
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003590 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003591 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003592 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003593 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003594 return uniPort, outPort
3595 }
3596 }
3597 } else {
3598 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003599 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003600 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003601 return inPort, uniPort
3602 }
3603 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003604 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003605 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003606 return uniPort, outPort
3607 }
3608 }
3609 }
3610
3611 return InvalidPort, InvalidPort
3612}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003613
3614func extractOmciTransactionID(omciPkt []byte) uint16 {
3615 if len(omciPkt) > 3 {
3616 d := omciPkt[0:2]
3617 transid := binary.BigEndian.Uint16(d)
3618 return transid
3619 }
3620 return 0
3621}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003622
3623// StoreOnuDevice stores the onu parameters to the local cache.
3624func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3625 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3626 dh.onus.Store(onuKey, onuDevice)
3627}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003628
khenaidoodc2116e2021-10-19 17:33:19 -04003629func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003630 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003631 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003632 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003633 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003634 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003635 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003636 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003637 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3638 return nil, err
3639 }
3640 ID = device.ProxyAddress.GetOnuId()
3641 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3642 valueparam.Onu = &Onu
3643 valueparam.Value = value
3644
3645 // This API is unsupported until agent patch is added
3646 resp.Unsupported = uint32(value)
3647 _ = ctx
3648
3649 // Uncomment this code once agent changes are complete and tests
3650 /*
3651 resp, err = dh.Client.GetValue(ctx, valueparam)
3652 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003653 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003654 return nil, err
3655 }
3656 */
3657
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003658 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 -08003659 return resp, nil
3660}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003661
Akash Kankanala041a2122024-10-16 15:49:22 +05303662func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003663 // Default to NNI
3664 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003665 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003666 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003667 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003668 }
3669 return intfID
3670}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003671
Akash Kankanala041a2122024-10-16 15:49:22 +05303672func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003673 dh.perPonOnuIndicationChannelLock.Lock()
3674 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3675 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003676 return ch.indicationChannel
3677 }
3678 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303679 // We create a buffered channel here to avoid calling function to be blocked
3680 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003681 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003682 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003683 stopChannel: make(chan struct{}),
3684 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003685 dh.perPonOnuIndicationChannel[intfID] = channels
3686 dh.perPonOnuIndicationChannelLock.Unlock()
3687 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003688 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003689}
3690
Mahir Gunyelb0046752021-02-26 13:51:05 -08003691func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3692 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3693 dh.perPonOnuIndicationChannelLock.Lock()
3694 defer dh.perPonOnuIndicationChannelLock.Unlock()
3695 for _, v := range dh.perPonOnuIndicationChannel {
3696 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003697 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003698 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003699}
3700
Mahir Gunyelb0046752021-02-26 13:51:05 -08003701func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3702 ind := onuIndicationMsg{
3703 ctx: ctx,
3704 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003705 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003706 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003707 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303708 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003709}
3710
Mahir Gunyelb0046752021-02-26 13:51:05 -08003711func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003712 for {
3713 select {
3714 // process one indication per onu, before proceeding to the next one
3715 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003716 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003717 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003718 "ind": indication})
3719 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003720 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003721 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003722 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3723 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003724 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003725 }
3726 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003727 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003728 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3729 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003730 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003731 }
3732 }
3733 case <-onuChannels.stopChannel:
3734 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3735 close(onuChannels.indicationChannel)
3736 return
3737 }
3738 }
3739}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003740
3741// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3742// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003743func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003744 if dh.getDeviceDeletionInProgressFlag() {
3745 // The device itself is going to be reset as part of deletion. So nothing to be done.
3746 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3747 return nil
3748 }
3749
Girish Gowdra491a9c62021-01-06 16:43:07 -08003750 // Step1 : Fill McastFlowOrGroupControlBlock
3751 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3752 // Step3 : Wait on response channel for response
3753 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003754 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003755 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3756 errChan := make(chan error)
3757 var groupID uint32
3758 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3759 ctx: ctx,
3760 flowOrGroupAction: action,
3761 flow: flow,
3762 group: group,
3763 errChan: &errChan,
3764 }
3765 if flow != nil {
3766 groupID = flow_utils.GetGroup(flow)
3767 } else if group != nil {
3768 groupID = group.Desc.GroupId
3769 } else {
3770 return errors.New("flow-and-group-both-nil")
3771 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003772 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3773 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3774 // Derive the appropriate go routine to handle the request by a simple module operation.
3775 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3776 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3777 // Wait for handler to return error value
3778 err := <-errChan
3779 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3780 return err
3781 }
3782 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3783 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003784}
3785
3786// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003787func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003788 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003789 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003790 // block on the channel to receive an incoming mcast flow/group
3791 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003792 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3793 if mcastFlowOrGroupCb.flow != nil {
3794 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3795 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3796 log.Fields{"device-id": dh.device.Id,
3797 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003798 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3799 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3800 for _, flMgr := range dh.flowMgr {
3801 if flMgr != nil {
3802 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3803 break
3804 }
3805 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003806 // Pass the return value over the return channel
3807 *mcastFlowOrGroupCb.errChan <- err
3808 } else { // flow remove
3809 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3810 log.Fields{"device-id": dh.device.Id,
3811 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003812 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3813 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3814 for _, flMgr := range dh.flowMgr {
3815 if flMgr != nil {
3816 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3817 break
3818 }
3819 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003820 // Pass the return value over the return channel
3821 *mcastFlowOrGroupCb.errChan <- err
3822 }
3823 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303824 switch mcastFlowOrGroupCb.flowOrGroupAction {
3825 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003826 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3827 log.Fields{"device-id": dh.device.Id,
3828 "groupToAdd": mcastFlowOrGroupCb.group})
3829 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3830 // Pass the return value over the return channel
3831 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303832 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003833 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3834 log.Fields{"device-id": dh.device.Id,
3835 "groupToModify": mcastFlowOrGroupCb.group})
3836 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3837 // Pass the return value over the return channel
3838 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303839 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003840 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3841 log.Fields{"device-id": dh.device.Id,
3842 "groupToRemove": mcastFlowOrGroupCb.group})
3843 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3844 // Pass the return value over the return channel
3845 *mcastFlowOrGroupCb.errChan <- err
3846 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003847 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003848 case <-stopHandler:
3849 dh.mcastHandlerRoutineActive[routineIndex] = false
3850 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003851 }
3852 }
3853}
kesavand62126212021-01-12 04:56:06 -05003854
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003855// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003856func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003857 for i, v := range dh.stopMcastHandlerRoutine {
3858 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003859 select {
3860 case v <- true:
3861 case <-time.After(time.Second * 5):
3862 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3863 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003864 }
3865 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003866
3867 if dh.incomingMcastFlowOrGroup != nil {
3868 for k := range dh.incomingMcastFlowOrGroup {
3869 if dh.incomingMcastFlowOrGroup[k] != nil {
3870 dh.incomingMcastFlowOrGroup[k] = nil
3871 }
3872 }
3873 dh.incomingMcastFlowOrGroup = nil
3874 }
3875
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003876 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003877 logger.Debug(ctx, "stopped all mcast handler routines")
3878}
3879
Akash Kankanala041a2122024-10-16 15:49:22 +05303880// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003881func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003882 singleValResp := extension.SingleGetValueResponse{
3883 Response: &extension.GetValueResponse{
3884 Response: &extension.GetValueResponse_PortCoutners{
3885 PortCoutners: &extension.GetOltPortCountersResponse{},
3886 },
3887 },
3888 }
3889
Akash Kankanala041a2122024-10-16 15:49:22 +05303890 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003891 return &extension.SingleGetValueResponse{
3892 Response: &extension.GetValueResponse{
3893 Status: status,
3894 ErrReason: reason,
3895 },
3896 }
3897 }
3898
3899 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3900 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303901 // send error response
kesavand62126212021-01-12 04:56:06 -05003902 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3903 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3904 }
3905 statIndChn := make(chan bool, 1)
3906 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3907 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303908 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003909
3910 go func() {
bseenivaa1622112025-12-11 18:24:02 +05303911 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3912 _, err := dh.Client.CollectStatistics(subCtx, new(oop.Empty))
kesavand62126212021-01-12 04:56:06 -05003913 if err != nil {
3914 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3915 }
bseenivaa1622112025-12-11 18:24:02 +05303916 cancel()
kesavand62126212021-01-12 04:56:06 -05003917 }()
3918 select {
3919 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303920 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003921 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3922 case <-time.After(oltPortInfoTimeout * time.Second):
3923 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3924 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3925 case <-ctx.Done():
3926 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3927 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3928 }
mgouda86543582025-10-29 20:58:16 +05303929 switch oltPortInfo.PortType {
3930 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303931 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003932 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003933 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3934 cmnni := dh.portStats.collectNNIMetrics(intfID)
3935 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303936 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003937 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3938 }
3939 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3940 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303941 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003942 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003943 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003944 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3945 cmpon := dh.portStats.collectPONMetrics(intfID)
3946 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303947 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003948 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3949 }
3950 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3951 return &singleValResp
3952 }
3953 }
3954 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3955}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303956
Akash Kankanala041a2122024-10-16 15:49:22 +05303957//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303958func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303959 singleValResp := extension.SingleGetValueResponse{
3960 Response: &extension.GetValueResponse{
3961 Status: extension.GetValueResponse_OK,
3962 Response: &extension.GetValueResponse_OffloadedAppsStats{
3963 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3964 },
3965 },
3966 }
3967
3968 return &singleValResp
3969}
3970
Akash Kankanala041a2122024-10-16 15:49:22 +05303971//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303972func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303973 singleValResp := extension.SingleSetValueResponse{
3974 Response: &extension.SetValueResponse{
3975 Status: extension.SetValueResponse_OK,
3976 },
3977 }
3978
3979 return &singleValResp
3980}
3981
Akash Kankanala041a2122024-10-16 15:49:22 +05303982//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303983func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303984 singleValResp := extension.SingleSetValueResponse{
3985 Response: &extension.SetValueResponse{
3986 Status: extension.SetValueResponse_OK,
3987 },
3988 }
3989
3990 return &singleValResp
3991}
3992
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303993func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303994 singleValResp := extension.SingleGetValueResponse{
3995 Response: &extension.GetValueResponse{
3996 Response: &extension.GetValueResponse_OnuPonCounters{
3997 OnuPonCounters: &extension.GetOnuCountersResponse{},
3998 },
3999 },
4000 }
4001
Akash Kankanala041a2122024-10-16 15:49:22 +05304002 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05304003 return &extension.SingleGetValueResponse{
4004 Response: &extension.GetValueResponse{
4005 Status: status,
4006 ErrReason: reason,
4007 },
4008 }
4009 }
4010 intfID := onuPonInfo.IntfId
4011 onuID := onuPonInfo.OnuId
4012 onuKey := dh.formOnuKey(intfID, onuID)
4013
4014 if _, ok := dh.onus.Load(onuKey); !ok {
4015 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
4016 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4017 }
4018 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
4019 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
4020 if cmnni == nil {
4021 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4022 }
4023 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
4024 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05304025}
Gamze Abaka85e9a142021-05-26 13:41:39 +00004026
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304027func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
4028 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
4029 if err != nil {
4030 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
4031 return nil, err
4032 }
4033 if onuGemInfo != nil {
4034 if len(onuGemInfo.UniPorts) == 0 {
4035 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
4036 return nil, err
4037 }
4038 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
4039 return onuGemInfo, nil
4040 }
4041 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
4042 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
4043}
4044
4045func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
4046 var err error
4047 var allocStats *oop.OnuAllocIdStatistics
4048 var onuGemStats *oop.GemPortStatistics
4049 for _, uni := range onuGemInfo.UniPorts {
4050 uniID := plt.UniIDFromPortNum(uni)
4051 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
4052 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
4053 if len(tpIDs) == 0 {
4054 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
4055 continue
4056 }
4057 for _, tpId := range tpIDs {
4058 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
4059 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
4060 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
4061 if techProfileInstance != nil {
4062 switch tpInst := techProfileInstance.(type) {
4063 case *tp_pb.TechProfileInstance:
4064 allocId := tpInst.UsScheduler.AllocId
4065 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
bseenivaa1622112025-12-11 18:24:02 +05304066 allocCtx, allocCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4067 allocStats, err = dh.Client.GetAllocIdStatistics(allocCtx, &onuAllocPkt)
4068 allocCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304069 if err != nil {
4070 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
4071 return err
4072 }
4073 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
4074 allocIdInfo.AllocId = allocStats.AllocId
4075 allocIdInfo.RxBytes = allocStats.RxBytes
4076
4077 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
4078
4079 gemPorts := tpInst.UpstreamGemPortAttributeList
4080 for _, gem := range gemPorts {
4081 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
bseenivaa1622112025-12-11 18:24:02 +05304082 gemCtx, gemCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4083 onuGemStats, err = dh.Client.GetGemPortStatistics(gemCtx, &onuGemPkt)
4084 gemCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304085 if err != nil {
4086 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
4087 return err
4088 }
4089 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
4090 gemStatsInfo.GemId = onuGemStats.GemportId
4091 gemStatsInfo.RxBytes = onuGemStats.RxBytes
4092 gemStatsInfo.RxPackets = onuGemStats.RxPackets
4093 gemStatsInfo.TxBytes = onuGemStats.TxBytes
4094 gemStatsInfo.TxPackets = onuGemStats.TxPackets
4095
4096 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
4097 }
4098 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
4099
4100 default:
4101 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4102 return err
4103 }
4104 } else {
4105 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4106 continue
4107 }
4108 }
4109 }
4110 return err
4111}
4112
4113//nolint:unparam
4114func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4115 singleValResp := extension.SingleGetValueResponse{
4116 Response: &extension.GetValueResponse{
4117 Status: extension.GetValueResponse_OK,
4118 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4119 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4120 },
4121 },
4122 }
4123 errResp := func(status extension.GetValueResponse_Status,
4124 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4125 return &extension.SingleGetValueResponse{
4126 Response: &extension.GetValueResponse{
4127 Status: status,
4128 ErrReason: reason,
4129 },
4130 }
4131 }
4132
4133 var intfID, onuID uint32
4134 if onuDevice != nil {
4135 onuID = onuDevice.ProxyAddress.OnuId
4136 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4137 }
4138
4139 onuKey := dh.formOnuKey(intfID, onuID)
4140 if _, ok := dh.onus.Load(onuKey); !ok {
4141 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4142 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4143 }
4144 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4145
4146 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4147 if err == nil {
4148 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4149 if err != nil {
4150 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4151 }
4152 } else {
4153 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4154 }
4155 return &singleValResp
4156}
4157
nikesh.krishnanc8473432023-06-14 12:14:54 +05304158func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304159 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
bseenivaa1622112025-12-11 18:24:02 +05304160 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4161 OnuInfo, err := dh.Client.GetOnuInfo(subCtx, &Onu)
4162 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304163 if err != nil {
4164 return nil, err
4165 }
4166 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304167}
4168
4169func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304170 Intf := oop.Interface{IntfId: intfID}
bseenivaa1622112025-12-11 18:24:02 +05304171 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4172 IntfInfo, err := dh.Client.GetPonInterfaceInfo(subCtx, &Intf)
4173 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304174 if err != nil {
4175 return nil, err
4176 }
4177 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304178}
4179
Gamze Abaka85e9a142021-05-26 13:41:39 +00004180func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004181 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
bseenivaa1622112025-12-11 18:24:02 +05304182 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4183 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4184 cancel()
Gamze Abaka85e9a142021-05-26 13:41:39 +00004185 if err != nil {
4186 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4187 return generateSingleGetValueErrorResponse(err)
4188 }
4189 return &extension.SingleGetValueResponse{
4190 Response: &extension.GetValueResponse{
4191 Status: extension.GetValueResponse_OK,
4192 Response: &extension.GetValueResponse_RxPower{
4193 RxPower: &extension.GetRxPowerResponse{
4194 IntfId: rxPowerRequest.IntfId,
4195 OnuId: rxPowerRequest.OnuId,
4196 Status: rxPower.Status,
4197 FailReason: rxPower.FailReason.String(),
4198 RxPower: rxPower.RxPowerMeanDbm,
4199 },
4200 },
4201 },
4202 }
4203}
4204
praneeth nalmas55616d62023-02-06 09:19:18 +05304205func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304206 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304207 return &extension.SingleGetValueResponse{
4208 Response: &extension.GetValueResponse{
4209 Status: status,
4210 ErrReason: reason,
4211 },
4212 }
4213 }
4214
4215 resp := extension.SingleGetValueResponse{
4216 Response: &extension.GetValueResponse{
4217 Status: extension.GetValueResponse_OK,
4218 Response: &extension.GetValueResponse_OltRxPower{
4219 OltRxPower: &extension.GetOltRxPowerResponse{},
4220 },
4221 },
4222 }
4223
4224 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4225 portLabel := OltRxPowerRequest.PortLabel
4226 serialNumber := OltRxPowerRequest.OnuSn
4227
4228 portInfo := strings.Split(portLabel, "-")
4229 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4230
4231 if err != nil {
4232 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4233 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4234 }
4235
4236 if portInfo[0] != "pon" {
4237 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4238 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4239 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304240
4241 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304242 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4243 if onuDev != nil {
bseenivaa1622112025-12-11 18:24:02 +05304244 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
praneeth nalmas55616d62023-02-06 09:19:18 +05304245 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
bseenivaa1622112025-12-11 18:24:02 +05304246 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4247 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304248 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304249 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4250 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304251 }
4252
4253 rxPowerValue := extension.RxPower{}
4254 rxPowerValue.OnuSn = onuDev.serialNumber
4255 rxPowerValue.Status = rxPower.GetStatus()
4256 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4257 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4258
4259 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304260 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304261 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4262 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4263 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304264 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304265 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304266 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304267 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
bseenivaa1622112025-12-11 18:24:02 +05304268 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4269 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4270 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304271 if err != nil {
4272 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4273 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304274 rxPowerValue := extension.RxPower{}
4275 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4276 rxPowerValue.Status = rxPower.GetStatus()
4277 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4278 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4279
4280 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4281 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304282 }
4283 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4284 return true
4285 })
4286 }
4287 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4288 return &resp
4289}
4290
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304291func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4292 errResp := func(status extension.GetValueResponse_Status,
4293 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4294 return &extension.SingleGetValueResponse{
4295 Response: &extension.GetValueResponse{
4296 Status: status,
4297 ErrReason: reason,
4298 },
4299 }
4300 }
4301
4302 resp := extension.SingleGetValueResponse{
4303 Response: &extension.GetValueResponse{
4304 Status: extension.GetValueResponse_OK,
4305 Response: &extension.GetValueResponse_OltPonStatsResponse{
4306 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4307 },
4308 },
4309 }
4310
4311 portLabel := ponStatsRequest.GetPortLabel()
4312 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4313
4314 portInfo := strings.Split(portLabel, "-")
4315 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4316
4317 if err != nil {
4318 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4319 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4320 }
4321
4322 if portInfo[0] != "pon" {
4323 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4324 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4325 }
4326
4327 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304328 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4329 ponStats, err := dh.Client.GetPonPortStatistics(subCtx, &Interface)
4330 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304331 if err != nil {
4332 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4333 return generateSingleGetValueErrorResponse(err)
4334 }
4335
4336 ponPortStats := resp.Response.GetOltPonStatsResponse()
4337 ponPortStats.PonPort = uint32(portNumber)
4338 ponPortStats.PortStatistics = ponStats
4339
4340 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4341 return &resp
4342}
4343
4344func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4345 errResp := func(status extension.GetValueResponse_Status,
4346 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4347 return &extension.SingleGetValueResponse{
4348 Response: &extension.GetValueResponse{
4349 Status: status,
4350 ErrReason: reason,
4351 },
4352 }
4353 }
4354
4355 resp := extension.SingleGetValueResponse{
4356 Response: &extension.GetValueResponse{
4357 Status: extension.GetValueResponse_OK,
4358 Response: &extension.GetValueResponse_OltNniStatsResponse{
4359 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4360 },
4361 },
4362 }
4363
4364 portLabel := nniStatsRequest.GetPortLabel()
4365 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4366
4367 portInfo := strings.Split(portLabel, "-")
4368 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4369
4370 if err != nil {
4371 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4372 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4373 }
4374
4375 if portInfo[0] != "nni" {
4376 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4377 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4378 }
4379
4380 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304381 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4382 nniStats, err := dh.Client.GetNniPortStatistics(subCtx, &Interface)
4383 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304384 if err != nil {
4385 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4386 return generateSingleGetValueErrorResponse(err)
4387 }
4388
4389 nniPortStats := resp.Response.GetOltNniStatsResponse()
4390 nniPortStats.NniPort = uint32(portNumber)
4391 nniPortStats.PortStatistics = nniStats
4392
4393 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4394 return &resp
4395}
4396
Akash Kankanala041a2122024-10-16 15:49:22 +05304397// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004398func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304399 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004400 return &extension.SingleGetValueResponse{
4401 Response: &extension.GetValueResponse{
4402 Status: status,
4403 ErrReason: reason,
4404 },
4405 }
4406 }
4407
4408 if err != nil {
4409 if e, ok := status.FromError(err); ok {
4410 switch e.Code() {
4411 case codes.Internal:
4412 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4413 case codes.DeadlineExceeded:
4414 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4415 case codes.Unimplemented:
4416 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4417 case codes.NotFound:
4418 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4419 }
4420 }
4421 }
4422
4423 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4424}
khenaidoo106c61a2021-08-11 18:05:46 -04004425
4426/*
4427Helper functions to communicate with Core
4428*/
4429
4430func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4431 cClient, err := dh.coreClient.GetCoreServiceClient()
4432 if err != nil || cClient == nil {
4433 return nil, err
4434 }
4435 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4436 defer cancel()
4437 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4438}
4439
khenaidoodc2116e2021-10-19 17:33:19 -04004440func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004441 cClient, err := dh.coreClient.GetCoreServiceClient()
4442 if err != nil || cClient == nil {
4443 return nil, err
4444 }
4445 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4446 defer cancel()
4447 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4448}
4449
khenaidoodc2116e2021-10-19 17:33:19 -04004450func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004451 cClient, err := dh.coreClient.GetCoreServiceClient()
4452 if err != nil || cClient == nil {
4453 return err
4454 }
4455 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4456 defer cancel()
4457 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4458 return err
4459}
4460
4461func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4462 cClient, err := dh.coreClient.GetCoreServiceClient()
4463 if err != nil || cClient == nil {
4464 return nil, err
4465 }
4466 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4467 defer cancel()
4468 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4469}
4470
4471func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4472 cClient, err := dh.coreClient.GetCoreServiceClient()
4473 if err != nil || cClient == nil {
4474 return nil, err
4475 }
4476 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4477 defer cancel()
4478 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4479}
4480
4481func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) 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.DeviceUpdate(subCtx, device)
4489 return err
4490}
4491
khenaidoodc2116e2021-10-19 17:33:19 -04004492func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004493 cClient, err := dh.coreClient.GetCoreServiceClient()
4494 if err != nil || cClient == nil {
4495 return nil, err
4496 }
4497 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4498 defer cancel()
4499 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4500}
4501
khenaidoodc2116e2021-10-19 17:33:19 -04004502func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004503 cClient, err := dh.coreClient.GetCoreServiceClient()
4504 if err != nil || cClient == nil {
4505 return err
4506 }
4507 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4508 defer cancel()
4509 _, err = cClient.SendPacketIn(subCtx, pkt)
4510 return err
4511}
4512
4513func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4514 cClient, err := dh.coreClient.GetCoreServiceClient()
4515 if err != nil || cClient == nil {
4516 return err
4517 }
4518 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4519 defer cancel()
4520 _, err = cClient.PortCreated(subCtx, port)
4521 return err
4522}
4523
khenaidoodc2116e2021-10-19 17:33:19 -04004524func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004525 cClient, err := dh.coreClient.GetCoreServiceClient()
4526 if err != nil || cClient == nil {
4527 return err
4528 }
4529 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4530 defer cancel()
4531 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4532 return err
4533}
4534
khenaidoodc2116e2021-10-19 17:33:19 -04004535func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004536 cClient, err := dh.coreClient.GetCoreServiceClient()
4537 if err != nil || cClient == nil {
4538 return err
4539 }
4540 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4541 defer cancel()
4542 _, err = cClient.PortStateUpdate(subCtx, portState)
4543 return err
4544}
4545
khenaidoodc2116e2021-10-19 17:33:19 -04004546func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004547 cClient, err := dh.coreClient.GetCoreServiceClient()
4548 if err != nil || cClient == nil {
4549 return nil, err
4550 }
4551 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4552 defer cancel()
4553 return cClient.GetDevicePort(subCtx, portFilter)
4554}
4555
nikesh.krishnanc8473432023-06-14 12:14:54 +05304556func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4557 cClient, err := dh.coreClient.GetCoreServiceClient()
4558 if err != nil || cClient == nil {
4559 return nil, err
4560 }
4561 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4562 defer cancel()
4563 return cClient.GetPorts(subCtx, portFilter)
4564}
4565
khenaidoo106c61a2021-08-11 18:05:46 -04004566/*
4567Helper functions to communicate with child adapter
4568*/
4569
khenaidoodc2116e2021-10-19 17:33:19 -04004570func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004571 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4572 if err != nil || aClient == nil {
4573 return err
4574 }
4575 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4576 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4577 defer cancel()
4578 _, err = aClient.OmciIndication(subCtx, response)
4579 return err
4580}
4581
khenaidoodc2116e2021-10-19 17:33:19 -04004582func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004583 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4584 if err != nil || aClient == nil {
4585 return err
4586 }
4587 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4588 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4589 defer cancel()
4590 _, err = aClient.OnuIndication(subCtx, onuInd)
4591 return err
4592}
4593
khenaidoodc2116e2021-10-19 17:33:19 -04004594func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004595 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4596 if err != nil || aClient == nil {
4597 return err
4598 }
4599 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4600 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4601 defer cancel()
4602 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4603 return err
4604}
4605
khenaidoodc2116e2021-10-19 17:33:19 -04004606func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004607 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4608 if err != nil || aClient == nil {
4609 return err
4610 }
4611 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4612 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4613 defer cancel()
4614 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4615 return err
4616}
4617
khenaidoodc2116e2021-10-19 17:33:19 -04004618func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004619 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4620 if err != nil || aClient == nil {
4621 return err
4622 }
4623 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4624 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4625 defer cancel()
4626 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4627 return err
4628}
4629
4630/*
4631Helper functions for remote communication
4632*/
4633
4634// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4635// supports is deleted
4636func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05304637 logger.Debugw(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004638
4639 dh.lockChildAdapterClients.Lock()
4640 defer dh.lockChildAdapterClients.Unlock()
4641 if _, ok := dh.childAdapterClients[endpoint]; ok {
4642 // Already set
4643 return nil
4644 }
4645
4646 // Setup child's adapter grpc connection
4647 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004648 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4649 dh.cfg.AdapterEndpoint,
4650 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004651 "onu_inter_adapter_service.OnuInterAdapterService",
4652 dh.onuInterAdapterRestarted,
4653 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004654 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4655 return err
4656 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304657 retryCodes := []codes.Code{
4658 codes.Unavailable, // server is currently unavailable
4659 codes.DeadlineExceeded, // deadline for the operation was exceeded
4660 }
4661 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4662 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 -04004663
nikesh.krishnand9812542023-08-01 18:31:39 +05304664 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004665 // Wait until we have a connection to the child adapter.
4666 // Unlimited retries or until context expires
4667 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4668 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4669 for {
4670 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4671 if err == nil && client != nil {
4672 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4673 break
4674 }
4675 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4676 // Backoff
4677 if err = backoff.Backoff(subCtx); err != nil {
4678 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4679 break
4680 }
4681 }
4682 return nil
4683}
4684
khenaidoodc2116e2021-10-19 17:33:19 -04004685func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004686 // First check from cache
4687 dh.lockChildAdapterClients.RLock()
4688 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4689 dh.lockChildAdapterClients.RUnlock()
4690 return cgClient.GetOnuInterAdapterServiceClient()
4691 }
4692 dh.lockChildAdapterClients.RUnlock()
4693
4694 // Set the child connection - can occur on restarts
4695 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4696 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4697 cancel()
4698 if err != nil {
4699 return nil, err
4700 }
4701
4702 // Get the child client now
4703 dh.lockChildAdapterClients.RLock()
4704 defer dh.lockChildAdapterClients.RUnlock()
4705 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4706 return cgClient.GetOnuInterAdapterServiceClient()
4707 }
4708 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4709}
4710
4711func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4712 dh.lockChildAdapterClients.Lock()
4713 defer dh.lockChildAdapterClients.Unlock()
4714 for key, client := range dh.childAdapterClients {
4715 client.Stop(ctx)
4716 delete(dh.childAdapterClients, key)
4717 }
4718}
4719
khenaidooefff76e2021-12-15 16:51:30 -05004720// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4721func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4722 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004723 return nil
4724}
4725
khenaidooefff76e2021-12-15 16:51:30 -05004726// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4727func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4728 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004729 return nil
4730 }
khenaidooefff76e2021-12-15 16:51:30 -05004731 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004732}
Girish Gowdra950326e2021-11-05 12:43:24 -07004733
4734func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4735 dh.lockDevice.Lock()
4736 defer dh.lockDevice.Unlock()
4737 dh.isDeviceDeletionInProgress = flag
4738}
4739
4740func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4741 dh.lockDevice.RLock()
4742 defer dh.lockDevice.RUnlock()
4743 return dh.isDeviceDeletionInProgress
4744}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004745
4746// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4747// Returns false if waiting timed out.
4748func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4749 c := make(chan struct{})
4750 go func() {
4751 defer close(c)
4752 wg.Wait()
4753 }()
4754 select {
4755 case <-c:
4756 return true // completed normally
4757 case <-time.After(timeout):
4758 return false // timed out
4759 }
4760}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304761
4762func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4763 val, err := json.Marshal(signature)
4764 if err != nil {
4765 logger.Error(ctx, "failed-to-marshal")
4766 return
4767 }
4768 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4769 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4770 }
4771}
4772
4773func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4774 var signature uint32
4775
4776 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4777 if er == nil {
4778 if Value != nil {
4779 Val, er := kvstore.ToByte(Value.Value)
4780 if er != nil {
4781 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4782 return signature
4783 }
4784 if er = json.Unmarshal(Val, &signature); er != nil {
4785 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4786 return signature
4787 }
4788 }
4789 }
4790 return signature
4791}
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00004792
4793func (dh *DeviceHandler) UpdateDevice(ctx context.Context, updateDevice *voltha.UpdateDevice) {
4794 var dhCtx context.Context
4795 logger.Debug(ctx, "UpdateDevice called", log.Fields{"deviceConfig": updateDevice})
4796 dh.lockDevice.Lock()
4797 if dh.transitionHandlerCancel != nil {
4798 dh.transitionHandlerCancel() //if the previous device transition was grpc blocked on old IP,this make that handler return/exit.
4799 dh.transitionHandlerCancel = nil
4800 }
4801 err := updateDeviceAddress(dh.device, updateDevice) //update the device handler with the new device which would have newIP
4802 if err != nil {
4803 dh.lockDevice.Unlock()
4804 logger.Errorw(ctx, "failed-to-update-device-address", log.Fields{"error": err})
4805 return
4806 }
4807 connectStatus := dh.device.ConnectStatus
4808 dhCtx, dh.transitionHandlerCancel = context.WithCancel(context.Background())
4809 dh.lockDevice.Unlock()
4810 if connectStatus == voltha.ConnectStatus_REACHABLE {
4811 dh.updateStateUnreachable(dhCtx)
4812 } else {
4813 dh.transitionMap.Handle(dhCtx, DeviceInit)
4814 }
4815}
4816
4817func updateDeviceAddress(device *voltha.Device, deviceConfig *voltha.UpdateDevice) error {
4818 switch addr := deviceConfig.Address.(type) {
4819 case *voltha.UpdateDevice_Ipv4Address:
4820 if current, ok := device.Address.(*voltha.Device_Ipv4Address); ok {
4821 if current.Ipv4Address == addr.Ipv4Address {
4822 return fmt.Errorf("no-change-in-IPV4-device-address")
4823 }
4824 device.Address = &voltha.Device_Ipv4Address{Ipv4Address: addr.Ipv4Address}
4825 }
4826 case *voltha.UpdateDevice_Ipv6Address:
4827 if current, ok := device.Address.(*voltha.Device_Ipv6Address); ok {
4828 if current.Ipv6Address == addr.Ipv6Address {
4829 return fmt.Errorf("no-change-in-IPV6-device-address")
4830 }
4831 device.Address = &voltha.Device_Ipv6Address{Ipv6Address: addr.Ipv6Address}
4832 }
4833 case *voltha.UpdateDevice_HostAndPort:
4834 if current, ok := device.Address.(*voltha.Device_HostAndPort); ok {
4835 if current.HostAndPort == addr.HostAndPort {
4836 return fmt.Errorf("no-change-in-HostAndPort-device-address")
4837 }
4838 device.Address = &voltha.Device_HostAndPort{HostAndPort: addr.HostAndPort}
4839 }
4840 default:
4841 return fmt.Errorf("invalid-device-config-address-type")
4842 }
4843 return nil
4844}