blob: 05e85ffbb3d77cdf58d797355b699fbdb8f3a0f5 [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
bseeniva0b9cbcb2026-02-12 19:11:11 +053033 "github.com/gogo/protobuf/proto"
Elia Battiston599d25f2022-02-16 14:49:08 +010034 "github.com/opencord/voltha-lib-go/v7/pkg/db"
35 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
36
khenaidoo106c61a2021-08-11 18:05:46 -040037 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040038
Matteo Scandolo945e4012019-12-12 14:16:11 -080039 "github.com/cenkalti/backoff/v3"
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
bseeniva0b9cbcb2026-02-12 19:11:11 +0530218 // Note: We use the device directly instead of cloning to avoid issues with protobuf unexported fields
219 dh.device = device
cuilin20187b2a8c32019-03-26 19:52:28 -0700220 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?
bseeniva0b9cbcb2026-02-12 19:11:11 +0530225 dh.metrics = pmmetrics.NewPmMetrics(device.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 {
balaji.nagarajan8f95de32026-02-01 11:39:44 +0530524 defer logger.Infow(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
Akash Kankanala041a2122024-10-16 15:49:22 +05301156 // Update the device oper state and connection status
bseeniva0b9cbcb2026-02-12 19:11:11 +05301157 device.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001158 dh.lockDevice.Lock()
bseeniva0b9cbcb2026-02-12 19:11:11 +05301159 dh.device = device
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001160 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001161
khenaidoodc2116e2021-10-19 17:33:19 -04001162 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301163 DeviceId: device.Id,
1164 OperStatus: device.OperStatus,
1165 ConnStatus: device.ConnectStatus,
khenaidoo106c61a2021-08-11 18:05:46 -04001166 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001167 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001168 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001169
Akash Kankanala041a2122024-10-16 15:49:22 +05301170 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001171 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001172 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001173 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001174 }
1175 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001176 // Update onu state as down in onu adapter
1177 onuInd := oop.OnuIndication{}
1178 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001179
1180 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1181 if err != nil {
1182 return err
1183 }
1184 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001185 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001186 DeviceId: onuDevice.Id,
1187 OnuIndication: &onuInd,
1188 })
1189 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001191 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001192 "source": dh.openOLT.config.AdapterEndpoint,
bseeniva0b9cbcb2026-02-12 19:11:11 +05301193 "onu-indicator": onuInd.String(),
David K. Bainbridge794735f2020-02-11 21:01:37 -08001194 "device-type": onuDevice.Type,
1195 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301196 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001197 } else {
1198 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 -07001199 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001200 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001201 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001202 /* Discovered ONUs entries need to be cleared , since after OLT
1203 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301204 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001205 dh.lockDevice.Unlock()
1206
Neha Sharma96b7bf22020-06-15 10:37:32 +00001207 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001208 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301209}
1210
1211// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301212func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001213 var err error
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001214 dh.lockDevice.RLock()
1215 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.
1216 dh.lockDevice.RUnlock()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001217 // if the connection is already available, close the previous connection (olt reboot case)
1218 if dh.clientCon != nil {
1219 if err = dh.clientCon.Close(); err != nil {
1220 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1221 } else {
1222 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1223 }
1224 }
1225
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001226 logger.Debugw(ctx, "Dialing grpc", log.Fields{"device-id": dh.device.Id, "host-and-port": hostAndPort})
Abhay Kumard3f18512025-12-09 07:51:12 +00001227 grpc_prometheus.EnableClientHandlingTimeHistogram()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001228 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001229 dh.clientCon, err = grpc.DialContext(ctx, hostAndPort,
Girish Kumar93e91742020-07-27 16:43:19 +00001230 grpc.WithInsecure(),
1231 grpc.WithBlock(),
1232 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001233 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001234 grpc_prometheus.StreamClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001235 )),
1236 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001237 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001238 grpc_prometheus.UnaryClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001239 )))
1240
1241 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301242 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301243 "device-id": dh.device.Id,
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001244 "host-and-port": hostAndPort}, err)
Akash Sonif49299a2024-04-25 12:06:37 +05301245 }
1246
1247 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001248 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
Akash Sonif49299a2024-04-25 12:06:37 +05301249 DeviceId: dh.device.Id,
1250 OperStatus: voltha.OperStatus_RECONCILING,
1251 ConnStatus: voltha.ConnectStatus_REACHABLE,
1252 }); err != nil {
1253 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1254 }
1255 // 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
1256 // locally cached copy of the device struct.
1257 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1258 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1259 }
1260
Girish Gowdru0c588b22019-04-23 23:24:56 -04001261 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301262}
1263
1264// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301265func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001266 dh.Client = oop.NewOpenoltClient(dh.clientCon)
bseenivaa20d6c32026-01-11 21:51:19 +05301267 // decoupling it to avoid blocking state machine transition
1268 go dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001269 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301270}
1271
1272// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301273func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301274 var err error
balaji.nagarajan8f95de32026-02-01 11:39:44 +05301275 logger.Infow(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001276
1277 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001278 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301279 if err != nil || device == nil {
1280 /*TODO: needs to handle error scenarios */
1281 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1282 }
1283 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001284 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001285
bseeniva0b9cbcb2026-02-12 19:11:11 +05301286 device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1287 device.OperStatus = voltha.OperStatus_UNKNOWN
1288 dh.device = device
khenaidoo106c61a2021-08-11 18:05:46 -04001289
khenaidoodc2116e2021-10-19 17:33:19 -04001290 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301291 DeviceId: device.Id,
1292 OperStatus: device.OperStatus,
1293 ConnStatus: device.ConnectStatus,
khenaidoo106c61a2021-08-11 18:05:46 -04001294 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301295 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 -04001296 }
1297
bseenivaa1622112025-12-11 18:24:02 +05301298 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Chaitrashree G S44124192019-08-07 20:21:36 -04001299 // 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 +05301300 _, err = dh.Client.DisableOlt(subCtx, new(oop.Empty))
1301 cancel()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001302 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301303 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001304 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001305 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1306 // all the modules initialized and ready to handle incoming ONUs.
1307
Thomas Lee S985938d2020-05-04 11:40:41 +05301308 err = dh.initializeDeviceHandlerModules(ctx)
1309 if err != nil {
1310 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 -04001311 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001312
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001313 go startHeartbeatCheck(ctx, dh)
1314
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001315 return nil
1316 }
1317
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001318 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301319 logger.Error(ctx, "device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1320 cloned := proto.Clone(device).(*voltha.Device)
1321 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1322 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1323 dh.device = cloned
1324
1325 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
1326 DeviceId: cloned.Id,
1327 OperStatus: cloned.OperStatus,
1328 ConnStatus: cloned.ConnectStatus,
1329 }); err != nil {
1330 logger.Error(ctx, "device-state-update-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1331 }
1332 // decoupling it to avoid blocking state machine transition
1333 go dh.transitionMap.Handle(ctx, GrpcDisconnected)
1334 return nil
Girish Gowdru0c588b22019-04-23 23:24:56 -04001335 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301336
Neha Sharma96b7bf22020-06-15 10:37:32 +00001337 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001338
1339 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001341 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001342
1343 go startHeartbeatCheck(ctx, dh)
1344
cuilin20187b2a8c32019-03-26 19:52:28 -07001345 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301346}
1347
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001348func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001349 var err error
1350 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001351
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001352 if dh.flowMgr != nil {
1353 dh.StopAllFlowRoutines(ctx)
1354 }
1355
1356 dh.CloseKVClient(ctx)
1357
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001358 if err != nil {
1359 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1360 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001361 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1362 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301363 // If collector go routine is active, wait for it to stop
1364 dh.lockDevice.RLock()
1365 if dh.isCollectorActive {
1366 dh.lockDevice.RUnlock()
1367 dh.collectorWaitGroup.Wait()
1368 } else {
1369 dh.lockDevice.RUnlock()
1370 }
yasin saplid0566272021-12-21 09:10:30 +00001371 // +1 is for NNI
1372 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1373 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001374 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001375 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1376 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1377 // There is only one NNI manager since multiple NNI is not supported for now
1378 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001379 // Instantiate resource manager
1380 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 -07001381 return olterrors.ErrResourceManagerInstantiating
1382 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001383 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001384 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1385 // the KV store to manage mcast group data. Provide the first instance (0th index)
1386 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1387 return olterrors.ErrGroupManagerInstantiating
1388 }
yasin saplid0566272021-12-21 09:10:30 +00001389 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001390 // Instantiate flow manager
1391 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301392 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001393 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1394 } else {
1395 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001396 }
1397 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001398 /* TODO: Instantiate Alarm , stats , BW managers */
1399 /* Instantiating Event Manager to handle Alarms and KPIs */
1400 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1401
1402 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001403 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001404
1405 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001406}
1407
Neha Sharma96b7bf22020-06-15 10:37:32 +00001408func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001409 var err error
1410 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301411 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001412
bseenivaa1622112025-12-11 18:24:02 +05301413 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1414 deviceInfo, err = dh.Client.GetDeviceInfo(subCtx, new(oop.Empty))
1415 cancel()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001416
1417 if err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301418 return nil, olterrors.NewErrCommunication("get-device-info-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001419 }
1420 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001422 }
1423
Neha Sharma96b7bf22020-06-15 10:37:32 +00001424 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001425 dh.device.Root = true
1426 dh.device.Vendor = deviceInfo.Vendor
1427 dh.device.Model = deviceInfo.Model
1428 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1429 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1430 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1431
1432 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001433 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001434 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301435 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001436 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001437 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001438 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001439 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001440 dh.device.MacAddress = genmac
1441 } else {
1442 dh.device.MacAddress = deviceInfo.DeviceId
1443 }
1444
1445 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001446 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001447 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001448 }
1449
1450 return deviceInfo, nil
1451}
1452
Neha Sharma96b7bf22020-06-15 10:37:32 +00001453func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301454 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001455
1456 defer func() {
1457 dh.lockDevice.Lock()
1458 dh.isCollectorActive = false
1459 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301460 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001461 }()
1462
1463 dh.lockDevice.Lock()
1464 dh.isCollectorActive = true
1465 dh.lockDevice.Unlock()
1466
Naga Manjunath7615e552019-10-11 22:35:47 +05301467 for {
1468 select {
1469 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301470 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301471 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001472 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001473
khenaidoo106c61a2021-08-11 18:05:46 -04001474 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001475 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001476 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001477 continue
1478 }
khenaidoo106c61a2021-08-11 18:05:46 -04001479 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301480 // NNI Stats
1481 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001482 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301483 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001485 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001486 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301487 }
1488 // PON Stats
1489 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001490 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301491 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1492 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001493 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001494 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301495 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001496 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001497
yasin sapli9e4c5092022-02-01 13:52:33 +00001498 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001499 if len(onuGemInfoLst) > 0 {
1500 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001501 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001502 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301503 }
1504 }
1505 }
1506}
1507
Mahir Gunyela2e68702022-12-07 00:00:42 -08001508// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301509func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001510 var dhCtx context.Context
Girish Gowdru0c588b22019-04-23 23:24:56 -04001511 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001512 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00001513 dhCtx, dh.transitionHandlerCancel = context.WithCancel(context.Background())
1514 dh.transitionMap.Handle(dhCtx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301515
1516 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001517 cgClient, err := dh.coreClient.GetCoreServiceClient()
1518 if err != nil {
1519 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1520 return
1521 }
1522
1523 // Now, set the initial PM configuration for that device
1524 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001525 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301526 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301527}
1528
Mahir Gunyela2e68702022-12-07 00:00:42 -08001529// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001530func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1531 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001532 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301533 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001534 HwDesc: "open_pon",
1535 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001536 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001537 },
1538 SwitchFeatures: &of.OfpSwitchFeatures{
1539 NBuffers: 256,
1540 NTables: 2,
1541 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1542 of.OfpCapabilities_OFPC_TABLE_STATS |
1543 of.OfpCapabilities_OFPC_PORT_STATS |
1544 of.OfpCapabilities_OFPC_GROUP_STATS),
1545 },
1546 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301547}
1548
khenaidoo106c61a2021-08-11 18:05:46 -04001549// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001550func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001551 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001552 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001553 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001554 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001555 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1556 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()
1557 }
khenaidoo106c61a2021-08-11 18:05:46 -04001558 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001559}
1560
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001562 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 -07001563 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001564 var deviceID string
1565 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001566 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001567
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001568 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001569 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 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 -07001571 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1572 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001573
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001574 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301575
1576 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 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 -07001578 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001579
khenaidoodc2116e2021-10-19 17:33:19 -04001580 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001581 ParentId: dh.device.Id,
1582 OnuId: omciInd.OnuId,
1583 ParentPortNo: ponPort,
1584 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001585 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301586 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001587 "intf-id": omciInd.IntfId,
1588 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001589 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001590 deviceType = onuDevice.Type
1591 deviceID = onuDevice.Id
1592 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001593 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301594 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001595 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001596 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301597 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 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 +05301599 deviceType = onuInCache.(*OnuDevice).deviceType
1600 deviceID = onuInCache.(*OnuDevice).deviceID
1601 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001602 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001603 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001604
khenaidoodc2116e2021-10-19 17:33:19 -04001605 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001606 ParentDeviceId: proxyDeviceID,
1607 ChildDeviceId: deviceID,
1608 Message: omciInd.Pkt,
1609 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301610 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001611 "source": dh.openOLT.config.AdapterEndpoint,
1612 "device-type": deviceType,
1613 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001614 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001615 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001616 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301618}
1619
khenaidoo106c61a2021-08-11 18:05:46 -04001620// //ProcessInterAdapterMessage sends the proxied messages to the target device
1621// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1622// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001623// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001624// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001625// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001626// return dh.handleInterAdapterOmciMsg(ctx, msg)
1627// }
1628// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1629// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001630
kesavandb9f54fd2021-11-25 20:08:04 +05301631// ProxyOmciRequests sends the proxied OMCI message to the target device
1632func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301633 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1634 return status.Error(codes.Unavailable, "OLT unreachable")
1635 }
kesavandb9f54fd2021-11-25 20:08:04 +05301636 if omciMsgs.GetProxyAddress() == nil {
1637 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1638 if err != nil {
1639 return olterrors.NewErrNotFound("onu", log.Fields{
1640 "parent-device-id": dh.device.Id,
1641 "child-device-id": omciMsgs.ChildDeviceId}, err)
1642 }
1643 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1644 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1645 return olterrors.NewErrCommunication("send-failed", log.Fields{
1646 "parent-device-id": dh.device.Id,
1647 "child-device-id": omciMsgs.ChildDeviceId}, err)
1648 }
1649 } else {
1650 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1651 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1652 return olterrors.NewErrCommunication("send-failed", log.Fields{
1653 "parent-device-id": dh.device.Id,
1654 "child-device-id": omciMsgs.ChildDeviceId}, err)
1655 }
1656 }
1657 return nil
1658}
1659
1660func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1661 var intfID uint32
1662 var onuID uint32
1663 var connectStatus common.ConnectStatus_Types
1664 if onuDevice != nil {
1665 intfID = onuDevice.ProxyAddress.GetChannelId()
1666 onuID = onuDevice.ProxyAddress.GetOnuId()
1667 connectStatus = onuDevice.ConnectStatus
1668 } else {
1669 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1670 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1671 connectStatus = omciMsgs.GetConnectStatus()
1672 }
1673 if connectStatus != voltha.ConnectStatus_REACHABLE {
1674 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1675
1676 return olterrors.NewErrCommunication("unreachable", log.Fields{
1677 "intf-id": intfID,
1678 "onu-id": onuID}, nil)
1679 }
1680
1681 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1682 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1683
1684 onuSecOmciMsgList := omciMsgs.GetMessages()
1685
1686 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301687 var omciMessage *oop.OmciMsg
1688 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1689 hex.Encode(hexPkt, onuSecOmciMsg)
1690 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1691
1692 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1693 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1694 //https://jira.opencord.org/browse/VOL-4604
1695 transid := extractOmciTransactionID(onuSecOmciMsg)
1696 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1697 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1698
bseenivaa1622112025-12-11 18:24:02 +05301699 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1700 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1701 cancel()
kesavandb9f54fd2021-11-25 20:08:04 +05301702 if err != nil {
1703 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1704 "intf-id": intfID,
1705 "onu-id": onuID,
1706 "message": omciMessage}, err)
1707 }
1708 }
1709 return nil
1710}
1711
khenaidoo106c61a2021-08-11 18:05:46 -04001712// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001713func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001714 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 -07001715
Akash Reddy Kankanala7b4d57e2026-01-26 23:18:18 +05301716 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) || DeviceState(dh.device.OperStatus) != DeviceState(voltha.OperStatus_ACTIVE) {
1717 return status.Error(codes.Unavailable, "OLT-is-unreachable-or-not-active")
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301718 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001719 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001720 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001721 if err != nil {
1722 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001723 "parent-device-id": dh.device.Id,
1724 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001725 }
khenaidoo106c61a2021-08-11 18:05:46 -04001726 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1727 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001728 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001729 "parent-device-id": dh.device.Id,
1730 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001731 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001732 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001733 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1734 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001735 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001736 "parent-device-id": dh.device.Id,
1737 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001738 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001739 }
1740 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301741}
1742
khenaidoodc2116e2021-10-19 17:33:19 -04001743func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001744 var intfID uint32
1745 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001746 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001747 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001748 intfID = onuDevice.ProxyAddress.GetChannelId()
1749 onuID = onuDevice.ProxyAddress.GetOnuId()
1750 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001751 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001752 intfID = omciMsg.GetProxyAddress().GetChannelId()
1753 onuID = omciMsg.GetProxyAddress().GetOnuId()
1754 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001755 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001756 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001757 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 -08001758
Thomas Lee S94109f12020-03-03 16:39:29 +05301759 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001760 "intf-id": intfID,
1761 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001762 }
1763
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001764 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1765 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301766 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001767 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001768 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1769 hex.Encode(hexPkt, omciMsg.Message)
1770 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1771
1772 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1773 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1774 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001776 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001777
bseenivaa1622112025-12-11 18:24:02 +05301778 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1779 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1780 cancel()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001781 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301782 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001783 "intf-id": intfID,
1784 "onu-id": onuID,
1785 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001786 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001787 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001788}
1789
David K. Bainbridge794735f2020-02-11 21:01:37 -08001790func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301791 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 +00001792 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001793 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001794 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001795 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301796 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
bseenivaa1622112025-12-11 18:24:02 +05301797 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1798 defer cancel()
1799 if _, err := dh.Client.ActivateOnu(subCtx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001800 st, _ := status.FromError(err)
1801 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802 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 -04001803 } else {
bseeniva0b9cbcb2026-02-12 19:11:11 +05301804 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu-serial": serialNumber, "onu-id": onuID, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001805 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001806 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001808 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001809 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001810}
1811
Mahir Gunyela2e68702022-12-07 00:00:42 -08001812// getChildDevice function can be used in general to get child device, if not found in cache the function will
1813// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301814func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1815 var InCacheOnuDev *OnuDevice
1816 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1817 if onuInCache.(*OnuDevice).serialNumber == sn {
1818 InCacheOnuDev = onuInCache.(*OnuDevice)
1819 return false
1820 }
1821 return true
1822 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301823 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301824 if InCacheOnuDev != nil {
1825 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1826 return InCacheOnuDev
1827 }
1828 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1829 ParentId: dh.device.Id,
1830 SerialNumber: sn,
1831 ParentPortNo: parentPortNo,
1832 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301833 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301834 if onuDevice == nil {
1835 return nil
1836 }
1837 onuID := onuDevice.ProxyAddress.OnuId
1838 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1839 onuKey := dh.formOnuKey(intfID, onuID)
1840
1841 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1842 dh.onus.Store(onuKey, onuDev)
1843 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1844 return onuDev
1845}
1846
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301847// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1848// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301849func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001850 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301851 // 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 +05301852 // 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 +05301853 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
balaji.nagarajan90c15742026-01-30 10:08:24 +05301854 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301855 ParentId: dh.device.Id,
1856 SerialNumber: sn,
1857 ParentPortNo: parentPortNo,
1858 })
balaji.nagarajan90c15742026-01-30 10:08:24 +05301859 if err != nil {
1860 if e, ok := status.FromError(err); ok {
1861 switch e.Code() {
1862 case codes.NotFound:
1863 return false, nil
1864 default:
1865 logger.Errorw(ctx, "Unexpected error code while fetching device from core", log.Fields{"sn": sn, "error": err})
1866 return false, err
1867 }
1868 }
1869 }
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301870 if onuDevice != nil {
1871 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1872 return true, nil
1873 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05301874 logger.Debugw(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301875
1876 return false, nil
1877 } else {
1878 tpInstExists := false
1879 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301880 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1881 if onuDev != nil {
1882 var onuGemInfo *rsrcMgr.OnuGemInfo
1883 var err error
1884 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1885 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1886 return false, err
1887 }
1888 if onuGemInfo != nil {
1889 for _, uni := range onuGemInfo.UniPorts {
1890 uniID := plt.UniIDFromPortNum(uni)
1891 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1892 if len(tpIDs) != 0 {
1893 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1894 tpInstExists = true
1895 break
1896 }
1897 }
1898 }
1899 }
1900 return tpInstExists, nil
1901 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301902}
1903
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001904// processDiscONULOSClear clears the LOS Alarm if it's needed
1905func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301906 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001907 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301908
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001909 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1910 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1911 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1912 OnuLosRaise event sent for it */
1913 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1914 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1915 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1916 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1917 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1918 "currentIntfId": onuDiscInd.GetIntfId()})
1919 // TODO:: Should we need to ignore raising OnuLosClear event
1920 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301921 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001922 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1923 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1924 alarmInd.LosStatus = statusCheckOff
1925 go func() {
1926 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1927 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1928 }
1929 }()
1930 // stop iterating
1931 return false
1932 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301933 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001934 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301935}
1936
bseeniva43b5a912025-06-05 12:48:15 +05301937func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1938 if err != nil || tpInstExists {
1939 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1940 } else {
1941 // once the function completes set the value to false so that
1942 // we know the processing has inProcess.
1943 // Note that this is done after checking if we are already processing
1944 // to avoid changing the value from a different thread
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05301945 logger.Debugw(ctx, "onu-processing-completed", log.Fields{"sn": sn})
bseeniva43b5a912025-06-05 12:48:15 +05301946 dh.discOnus.Store(sn, false)
1947 }
1948}
1949
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301950func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301951 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301952 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301953
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301954 channelID := onuDiscInd.GetIntfId()
1955 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1956
1957 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301958 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301959 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301960 }()
1961
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301962 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1963
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301964 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1965 if !dh.cfg.ForceOnuDiscIndProcessing {
1966 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1967 if error != nil {
1968 return error
1969 }
1970 if tpInstExists {
1971 // ignore the discovery if tpinstance is present.
1972 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1973 return nil
1974 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001975 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001976 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1977
1978 // if the ONU existed, handle the LOS Alarm
1979 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001980 if inProcess.(bool) {
1981 // if we're currently processing the ONU on a different thread, do nothing
1982 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1983 return nil
1984 }
1985 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1986 // then continue processing it
1987 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1988
1989 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001990 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301991 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001992 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001993
1994 // check the ONU is already know to the OLT
1995 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301996 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001997 ParentId: dh.device.Id,
1998 SerialNumber: sn,
1999 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08002000
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302001 if error != nil {
2002 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
2003 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002004 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 -08002005 switch e.Code() {
balaji.nagarajan90c15742026-01-30 10:08:24 +05302006 case codes.Internal, codes.NotFound:
Matteo Scandolo945e4012019-12-12 14:16:11 -08002007 // this probably means NOT FOUND, so just create a new device
2008 onuDevice = nil
2009 case codes.DeadlineExceeded:
2010 // if the call times out, cleanup and exit
2011 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302012 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
2013 return error
balaji.nagarajan90c15742026-01-30 10:08:24 +05302014 default:
2015 //any other rpc errors
2016 dh.discOnus.Delete(sn)
2017 error = olterrors.NewErrAdapter("unexpected error code while fetching device from core", log.Fields{"device-id": dh.device.Id, "sn": sn}, error)
2018 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002019 }
2020 }
2021 }
2022
2023 if onuDevice == nil {
2024 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00002025 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002026 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04002027 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302028 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002030
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302031 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002032 // if we can't create an ID in resource manager,
2033 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08002034 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302035
2036 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002037 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302038 "serial-number": sn}, error)
2039 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002040 }
2041
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302042 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04002043 ParentId: dh.device.Id,
2044 ParentPortNo: parentPortNo,
2045 ChannelId: channelID,
2046 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
2047 SerialNumber: sn,
2048 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302049 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002050 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00002051 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 +05302052
2053 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002054 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302055 "serial-number": sn}, error)
2056 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002057 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302058 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 +05302059 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2060 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2061 "onu-id": onuID,
2062 "device-id": dh.device.Id,
2063 "serial-number": sn}, error)
2064 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002065 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302066 logger.Debugw(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302067 log.Fields{"onuDevice": onuDevice,
2068 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002069 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302070 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002071 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002072
khenaidoo106c61a2021-08-11 18:05:46 -04002073 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2074 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302075 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002076 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302077 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302078 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2079 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002080 }
2081
Matteo Scandolo945e4012019-12-12 14:16:11 -08002082 // we can now use the existing ONU Id
2083 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302084 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002085 //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 +00002086 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002087 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302088 "intfId": onuDiscInd.GetIntfId(),
2089 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002090 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002091
khenaidoo106c61a2021-08-11 18:05:46 -04002092 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302093 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002094 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302095 log.Fields{"onu": onuDev,
2096 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002097
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302098 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002099 DeviceId: onuDevice.Id,
2100 ParentDeviceId: dh.device.Id,
2101 OperStatus: common.OperStatus_DISCOVERED,
2102 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302103 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302104 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002105 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302106 "serial-number": sn}, error)
2107 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002108 }
khenaidoo106c61a2021-08-11 18:05:46 -04002109
Neha Sharma96b7bf22020-06-15 10:37:32 +00002110 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302111 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302112 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002113 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302114 "serial-number": sn}, error)
2115 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002116 }
2117 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002118}
2119
Mahir Gunyelb0046752021-02-26 13:51:05 -08002120func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002121 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002122 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002123 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002124 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302126 log.Fields{"onuId": onuInd.OnuId,
2127 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302128 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002129 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002130 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002131 errFields := log.Fields{"device-id": dh.device.Id}
2132
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302133 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302134 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002135 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002136 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002137 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002138 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302139 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002140 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002141 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002142 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002143 errFields["onu-id"] = onuInd.OnuId
2144 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002145 }
khenaidoodc2116e2021-10-19 17:33:19 -04002146 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002147 ParentId: dh.device.Id,
2148 SerialNumber: serialNumber,
2149 OnuId: onuInd.OnuId,
2150 ParentPortNo: ponPort,
2151 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002152 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002153
David K. Bainbridge794735f2020-02-11 21:01:37 -08002154 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002155 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002156 }
2157
David K. Bainbridge794735f2020-02-11 21:01:37 -08002158 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002159 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002160 "previousIntfId": onuDevice.ParentPortNo,
2161 "currentIntfId": ponPort})
2162 }
2163
2164 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002165 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302166 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2167 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302168 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002169 }
2170 if !foundInCache {
2171 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002172 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 -08002173 }
kesavand7cf3a052020-08-28 12:49:18 +05302174 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002175 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002176 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302177 }
2178 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002179 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002180 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002181 }
2182 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002183}
2184
Neha Sharma96b7bf22020-06-15 10:37:32 +00002185func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002186 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 -07002187 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2188 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2189 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2190 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002191 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002192 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2193 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002195 onuInd.OperState = "down"
2196 }
2197 }
2198
David K. Bainbridge794735f2020-02-11 21:01:37 -08002199 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002200 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002201 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 -04002202
khenaidoodc2116e2021-10-19 17:33:19 -04002203 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002204 DeviceId: onuDevice.Id,
2205 OnuIndication: onuInd,
2206 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002207 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302208 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002209 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002210 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002211 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002212 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002213 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002214 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002215 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002216 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002217 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002218}
2219
cuilin20187b2a8c32019-03-26 19:52:28 -07002220func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2221 if serialNum != nil {
2222 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002223 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002224 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002225}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002226func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2227 decodedStr, err := hex.DecodeString(serialNum[4:])
2228 if err != nil {
2229 return nil, err
2230 }
2231 return &oop.SerialNumber{
2232 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002233 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002234 }, nil
2235}
cuilin20187b2a8c32019-03-26 19:52:28 -07002236
2237func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002238 if len(vendorSpecific) > 3 {
2239 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2240 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2241 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2242 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2243 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2244 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2245 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2246 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2247 return tmp
2248 }
2249 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002250}
2251
Mahir Gunyela2e68702022-12-07 00:00:42 -08002252// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002253func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302254 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002255}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002256
Mahir Gunyela2e68702022-12-07 00:00:42 -08002257// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2259 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302260 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002261 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302262 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002263
khenaidoodc2116e2021-10-19 17:33:19 -04002264 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002265 ParentId: dh.device.Id,
2266 OnuId: onuID,
2267 ParentPortNo: parentPort,
2268 })
2269
Girish Gowdru0c588b22019-04-23 23:24:56 -04002270 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002271 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002272 "intf-id": parentPort,
2273 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002274 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002275 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 -08002276 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302277}
2278
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002279// SendPacketInToCore sends packet-in to core
2280// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2281// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002283 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002284 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002285 "port": logicalPort,
2286 "packet": hex.EncodeToString(packetPayload),
2287 "device-id": dh.device.Id,
2288 })
2289 }
khenaidoo106c61a2021-08-11 18:05:46 -04002290
khenaidoodc2116e2021-10-19 17:33:19 -04002291 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002292 DeviceId: dh.device.Id,
2293 Port: logicalPort,
2294 Packet: packetPayload,
2295 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302296 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002297 "source": "adapter",
2298 "destination": "core",
2299 "device-id": dh.device.Id,
2300 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002301 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002302 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002303 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002304 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002305 "packet": hex.EncodeToString(packetPayload),
2306 "device-id": dh.device.Id,
2307 })
2308 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002309 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002310}
2311
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002312// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002314 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002315
2316 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2317 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002319 }
2320
Kent Hagermane6ff1012020-07-14 15:07:53 -04002321 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002322 metrics := dh.metrics.GetSubscriberMetrics()
2323 for _, m := range pmConfigs.Metrics {
2324 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002325 }
2326 }
2327}
2328
khenaidoodc2116e2021-10-19 17:33:19 -04002329func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002330 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002331 var errorsList []error
2332
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002333 if dh.getDeviceDeletionInProgressFlag() {
2334 // The device itself is going to be reset as part of deletion. So nothing to be done.
2335 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2336 return nil
2337 }
2338
Girish Gowdru0c588b22019-04-23 23:24:56 -04002339 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002340 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302341 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002342
Neha Sharma96b7bf22020-06-15 10:37:32 +00002343 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302344 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002345 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302346 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002347 if flow_utils.HasGroup(flow) {
2348 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2349 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002350 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2351 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2352 } else {
2353 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2354 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002355 }
Girish Gowdracefae192020-03-19 18:14:10 -07002356 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002357 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302358 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002359 logger.Warnw(ctx, "flow-to-remove-not-found",
2360 log.Fields{
2361 "ponIf": intfID,
2362 "flowToRemove": flow,
2363 "error": err,
2364 })
2365 } else {
2366 errorsList = append(errorsList, err)
2367 }
Girish Gowdracefae192020-03-19 18:14:10 -07002368 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002369 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302370
2371 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302372 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002373 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302374 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002375 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302376 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002377 if flow_utils.HasGroup(flow) {
2378 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2379 } else {
yasin saplid0566272021-12-21 09:10:30 +00002380 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002381 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2382 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2383 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2384 } else {
yasin saplid0566272021-12-21 09:10:30 +00002385 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002386 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002387 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002388 if err != nil {
2389 errorsList = append(errorsList, err)
2390 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302391 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002392 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002393
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002394 return errorsList
2395}
2396
2397func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2398 var err error
2399 var errorsList []error
2400
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002401 if dh.getDeviceDeletionInProgressFlag() {
2402 // The device itself is going to be reset as part of deletion. So nothing to be done.
2403 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2404 return nil
2405 }
2406
Girish Gowdracefae192020-03-19 18:14:10 -07002407 // 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 +00002408 if groups != nil {
2409 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002410 // err = dh.groupMgr.AddGroup(ctx, group)
2411 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002412 if err != nil {
2413 errorsList = append(errorsList, err)
2414 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002415 }
2416 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002417 // err = dh.groupMgr.ModifyGroup(ctx, group)
2418 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002419 if err != nil {
2420 errorsList = append(errorsList, err)
2421 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002422 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002423 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002424 // err = dh.groupMgr.DeleteGroup(ctx, group)
2425 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002426 if err != nil {
2427 errorsList = append(errorsList, err)
2428 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002429 }
2430 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002431
2432 return errorsList
2433}
2434
Mahir Gunyela2e68702022-12-07 00:00:42 -08002435// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002436func (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 -07002437 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002438
2439 if dh.getDeviceDeletionInProgressFlag() {
2440 // The device itself is going to be reset as part of deletion. So nothing to be done.
2441 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2442 return nil
2443 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302444 if dh.transitionMap.currentDeviceState != deviceStateUp {
2445 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2446 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2447 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002448 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2449 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2450 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002451 if len(errorsList) > 0 {
2452 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2453 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002454 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002455 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302456}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002457
Mahir Gunyela2e68702022-12-07 00:00:42 -08002458// DisableDevice disables the given device
2459// It marks the following for the given device:
2460// Device-Handler Admin-State : down
2461// Device Port-State: UNKNOWN
2462// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002463func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002464 /* On device disable ,admin state update has to be done prior sending request to agent since
2465 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002466 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302467 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2468 if _, err := dh.Client.DisableOlt(subCtx, new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002469 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302470 cancel()
Girish Kumarf26e4882020-03-05 06:49:10 +00002471 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002472 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002473 }
bseenivaa1622112025-12-11 18:24:02 +05302474 cancel()
Chaitrashree G S44124192019-08-07 20:21:36 -04002475 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002477 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002478 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302479
2480 dh.discOnus = sync.Map{}
2481 dh.onus = sync.Map{}
2482
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002483 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302484 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002485 if dh.isCollectorActive {
2486 dh.stopCollector <- true
2487 }
2488 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302489
Neha Sharma96b7bf22020-06-15 10:37:32 +00002490 go dh.notifyChildDevices(ctx, "unreachable")
Akash Kankanala041a2122024-10-16 15:49:22 +05302491 // Update device Admin state
bseeniva0b9cbcb2026-02-12 19:11:11 +05302492 dh.device = device
khenaidoo106c61a2021-08-11 18:05:46 -04002493
kdarapu1afeceb2020-02-12 01:38:09 -05002494 // 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 -04002495 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
bseeniva0b9cbcb2026-02-12 19:11:11 +05302496 DeviceId: device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002497 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2498 OperStatus: voltha.OperStatus_UNKNOWN,
2499 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002500 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002501 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002503 return nil
2504}
2505
Neha Sharma96b7bf22020-06-15 10:37:32 +00002506func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002507 // Update onu state as unreachable in onu adapter
2508 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302509 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002510
Akash Kankanala041a2122024-10-16 15:49:22 +05302511 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002512 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002513 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002514 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 -04002515 }
2516 if onuDevices != nil {
2517 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002518 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002519 DeviceId: onuDevice.Id,
2520 OnuIndication: &onuInd,
2521 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002522 if err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05302523 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd.String(),
khenaidoo106c61a2021-08-11 18:05:46 -04002524 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002525 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002526 }
2527 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002528}
2529
Mahir Gunyela2e68702022-12-07 00:00:42 -08002530// ReenableDevice re-enables the olt device after disable
2531// It marks the following for the given device:
2532// Device-Handler Admin-State : up
2533// Device Port-State: ACTIVE
2534// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002535func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302536 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302537 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2538 if _, err := dh.Client.ReenableOlt(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302539 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302540 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302541 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2542 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302543 }
bseenivaa1622112025-12-11 18:24:02 +05302544 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302545 } else {
2546 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 +05302547 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002548 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002549
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002550 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002551 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002552 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002553 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002554 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2555 } else {
2556 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2557 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2558 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002559 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002560 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302561 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002562 device.OperStatus = voltha.OperStatus_ACTIVE
2563 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302564 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002565 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002566 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002567 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002568
khenaidoodc2116e2021-10-19 17:33:19 -04002569 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002570 DeviceId: device.Id,
2571 OperStatus: device.OperStatus,
2572 ConnStatus: device.ConnectStatus,
2573 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302574 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002575 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002576 "connect-status": device.ConnectStatus,
2577 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002578 }
kesavand39e0aa32020-01-28 20:58:50 -05002579
Neha Sharma96b7bf22020-06-15 10:37:32 +00002580 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002581
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002582 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002583}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002584
npujarec5762e2020-01-01 14:08:48 +05302585func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002586 var uniID uint32
2587 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002588 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302589 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002590 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002591 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002592 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002593 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2594 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2595 } else {
2596 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2597 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002598 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002599 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002600 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002601 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002602 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002603 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002604 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002605 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002606 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002607 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002608 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002609 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002610 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002611 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002613 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302614 }
yasin saplibddc2d72022-02-08 13:10:17 +00002615 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2616 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002617 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002618 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302619 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002620 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002621 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002622 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 -03002623 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002624 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002625 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002626 if len(errs) > 0 {
2627 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2628 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2629 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002630 return nil
2631}
2632
Devmalya Paul495b94a2019-08-27 19:42:00 -04002633// 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 +05302634func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002635 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002636 /* Clear the KV store data associated with the all the UNI ports
2637 This clears up flow data and also resource map data for various
2638 other pon resources like alloc_id and gemport_id
2639 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002640
Abhay Kumarb87ac882025-10-30 09:55:07 +00002641 if dh.getDeviceDeletionInProgressFlag() {
2642 logger.Errorw(ctx, "cannot complete operation as device deletion is in progress", log.Fields{"device-id": dh.device.Id})
2643 return olterrors.NewErrAdapter(fmt.Errorf("cannot complete operation as device deletion is in progress").Error(), log.Fields{"device-id": dh.device.Id}, nil)
2644 }
2645
Girish Gowdra950326e2021-11-05 12:43:24 -07002646 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002647 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002648
Himani Chawla49a5d562020-11-25 11:53:44 +05302649 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002650 // Stop the Stats collector
2651 if dh.isCollectorActive {
2652 dh.stopCollector <- true
2653 }
2654 // stop the heartbeat check routine
2655 if dh.isHeartbeatCheckActive {
2656 dh.stopHeartbeatCheck <- true
2657 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302658 // Stop the read indication only if it the routine is active
2659 if dh.isReadIndicationRoutineActive {
2660 dh.stopIndications <- true
2661 }
2662 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302663
2664 err := dh.cleanupDeviceResources(ctx)
2665 if err != nil {
2666 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 +05302667 dh.setDeviceDeletionInProgressFlag(false)
2668 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 +05302669 } else {
2670 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2671 }
2672
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002673 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302674 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002675 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302676 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2677 if _, err = dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002678 go func() {
2679 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302680 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2681 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002682 }
2683 }()
2684 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002685 }
bseenivaa1622112025-12-11 18:24:02 +05302686 cancel()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002687 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002688 // There is no need to update the core about operation status and connection status of the OLT.
2689 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2690 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2691 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002692
khenaidoo7eb2d672021-10-22 19:08:50 -04002693 // Stop the adapter grpc clients for that parent device
2694 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002695 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002696}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002697
2698// StopAllFlowRoutines stops all flow routines
2699func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2700 var wg sync.WaitGroup
2701 wg.Add(1) // for the mcast routine below to finish
2702 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2703 for _, flMgr := range dh.flowMgr {
2704 if flMgr != nil {
2705 wg.Add(1) // for the flow handler routine below to finish
2706 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2707 }
2708 }
2709 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2710 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2711 } else {
2712 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2713 }
2714}
2715
Gustavo Silva41af9122022-10-11 11:05:13 -03002716func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2717 var errs []error
Abhay Kumarb87ac882025-10-30 09:55:07 +00002718 if dh.resourceMgr != nil && dh.totalPonPorts > 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302719 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002720 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
balaji.nagarajanfa561fc2026-02-04 09:34:33 +05302721 if dh.resourceMgr[ponPort] == nil {
2722 logger.Warnw(ctx, "resource manager for ponPort is nil", log.Fields{"ponPort": ponPort})
2723 continue
2724 }
yasin sapli9e4c5092022-02-01 13:52:33 +00002725 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002726 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002727 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002728 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2729 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302730 }
2731 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002732 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2733 errs = append(errs, err)
2734 }
2735 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2736 errs = append(errs, err)
2737 }
2738 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2739 errs = append(errs, err)
2740 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002741 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002742 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002743 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002744 }
balaji.nagarajanfa561fc2026-02-04 09:34:33 +05302745 // Clean up NNI manager's data
2746 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2747 errs = append(errs, err)
2748 }
2749 } else {
2750 logger.Errorw(ctx, "resource manager empty, ignoring resource cleanup", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002751 }
A R Karthick1f85b802019-10-11 05:06:05 +00002752
balaji.nagarajan2e572c42026-01-27 15:09:39 +05302753 if len(errs) == 0 {
2754 // Take one final sweep at cleaning up KV store for the OLT device
2755 // Clean everything at <base-path-prefix>/openolt/<device-id>
2756 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2757 errs = append(errs, err)
2758 }
2759 logger.Debugw(ctx, "lockDevice for KVStore close client", log.Fields{"deviceID": dh.device.Id})
2760 dh.CloseKVClient(ctx)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002761 }
2762
Devmalya Paul495b94a2019-08-27 19:42:00 -04002763 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302764 dh.onus.Range(func(key interface{}, value interface{}) bool {
2765 dh.onus.Delete(key)
2766 return true
2767 })
2768
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002769 /*Delete discovered ONU map for the device*/
2770 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2771 dh.discOnus.Delete(key)
2772 return true
2773 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002774 if len(errs) > 0 {
2775 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2776 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2777 }
2778 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002779}
2780
Mahir Gunyela2e68702022-12-07 00:00:42 -08002781// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002782func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302783 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302784 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2785 defer cancel()
2786 if _, err := dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302787 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2788 }
2789 } else {
2790 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 -04002791 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302792
Neha Sharma96b7bf22020-06-15 10:37:32 +00002793 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002794 return nil
2795}
2796
David K. Bainbridge794735f2020-02-11 21:01:37 -08002797func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002798 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002799 logger.Debugw(ctx, "received-packet-in", log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05302800 "packet-indication": packetIn.String(),
Matteo Scandolo92186242020-06-12 10:54:18 -07002801 "device-id": dh.device.Id,
2802 "packet": hex.EncodeToString(packetIn.Pkt),
2803 })
2804 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002805 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2806 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2807 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002808 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002809 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002810 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002811 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002812 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002813 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002814 "logical-port-num": logicalPortNum,
2815 "device-id": dh.device.Id,
2816 "packet": hex.EncodeToString(packetIn.Pkt),
2817 })
2818 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002819
khenaidoodc2116e2021-10-19 17:33:19 -04002820 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002821 DeviceId: dh.device.Id,
2822 Port: logicalPortNum,
2823 Packet: packetIn.Pkt,
2824 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302825 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002826 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302827 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002828 "device-id": dh.device.Id,
2829 "packet": hex.EncodeToString(packetIn.Pkt),
2830 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002831 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002832
Matteo Scandolo92186242020-06-12 10:54:18 -07002833 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002834 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002835 "packet": hex.EncodeToString(packetIn.Pkt),
2836 "device-id": dh.device.Id,
2837 })
2838 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002839 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002840}
2841
Mahir Gunyela2e68702022-12-07 00:00:42 -08002842// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2843func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2844 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2845 if err != nil {
2846 return olterrors.NewErrInvalidValue(log.Fields{
2847 "egress-nni-port": egressPortNo,
2848 "device-id": dh.device.Id,
2849 }, err)
2850 }
2851 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2852
2853 if logger.V(log.DebugLevel) {
2854 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05302855 "uplink-pkt": uplinkPkt.String(),
Mahir Gunyela2e68702022-12-07 00:00:42 -08002856 "packet": hex.EncodeToString(packet.Data),
2857 "device-id": dh.device.Id,
2858 })
2859 }
2860
bseenivaa1622112025-12-11 18:24:02 +05302861 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2862 defer cancel()
2863 if _, err := dh.Client.UplinkPacketOut(subCtx, &uplinkPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002864 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2865 "packet": hex.EncodeToString(packet.Data),
2866 "device-id": dh.device.Id,
2867 }, err)
2868 }
2869 return nil
2870}
2871
2872// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2873func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2874 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2875 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2876 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2877 // Do not packet-out lldp packets on uni port.
2878 // ONOS has no clue about uni/nni ports, it just packets out on all
2879 // available ports on the Logical Switch. It should not be interested
2880 // in the UNI links.
2881 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2882 "device-id": dh.device.Id,
2883 })
2884 return nil
2885 }
2886 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2887 if innerEthType == 0x8100 {
2888 // q-in-q 802.1ad or 802.1q double tagged packet.
2889 // slice out the outer tag.
2890 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2891 if logger.V(log.DebugLevel) {
2892 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2893 "packet-data": hex.EncodeToString(packet.Data),
2894 "device-id": dh.device.Id,
2895 })
2896 }
2897 }
2898 }
2899 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2900 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2901 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2902 var gemPortID uint32
2903 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2904 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2905 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2906 }
2907 if err != nil {
2908 // In this case the openolt agent will receive the gemPortID as 0.
2909 // The agent tries to retrieve the gemPortID in this case.
2910 // This may not always succeed at the agent and packetOut may fail.
2911 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2912 "intf-id": intfID,
2913 "onu-id": onuID,
2914 "uni-id": uniID,
2915 "packet": hex.EncodeToString(packet.Data),
2916 "device-id": dh.device.Id,
2917 "error": err,
2918 })
2919 }
2920
2921 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2922 if logger.V(log.DebugLevel) {
2923 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2924 "egress-port-no": egressPortNo,
2925 "intf-id": intfID,
2926 "onu-id": onuID,
2927 "uni-id": uniID,
2928 "gem-port-id": gemPortID,
2929 "packet": hex.EncodeToString(packet.Data),
2930 "device-id": dh.device.Id,
2931 })
2932 }
2933
bseenivaa1622112025-12-11 18:24:02 +05302934 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2935 defer cancel()
2936 if _, err := dh.Client.OnuPacketOut(subCtx, &onuPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002937 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2938 "source": "adapter",
2939 "destination": "onu",
2940 "egress-port-number": egressPortNo,
2941 "intf-id": intfID,
2942 "oni-id": onuID,
2943 "uni-id": uniID,
2944 "gem-port-id": gemPortID,
2945 "packet": hex.EncodeToString(packet.Data),
2946 "device-id": dh.device.Id,
2947 }, err)
2948 }
2949 return nil
2950}
2951
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002952// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002953func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002954 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002955 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002956 "device-id": dh.device.Id,
2957 "egress-port-no": egressPortNo,
2958 "pkt-length": len(packet.Data),
2959 "packet": hex.EncodeToString(packet.Data),
2960 })
2961 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002962
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002963 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002964 var err error
mgouda86543582025-10-29 20:58:16 +05302965 switch egressPortType {
2966 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002967 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302968 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002969 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302970 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002971 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302972 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002973 "egressPortType": egressPortType,
2974 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302975 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002976 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002977 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002978 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002979}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002980
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002981func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2982 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002983}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302984
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002985func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002986 defer func() {
2987 dh.lockDevice.Lock()
2988 dh.isHeartbeatCheckActive = false
2989 dh.lockDevice.Unlock()
2990 }()
2991
2992 dh.lockDevice.Lock()
2993 dh.isHeartbeatCheckActive = true
2994 dh.lockDevice.Unlock()
2995
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302996 // start the heartbeat check towards the OLT.
2997 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302998 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302999
3000 for {
3001 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
3002 select {
3003 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00003004 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003005 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003006 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303007 if timerCheck == nil {
3008 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003009 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303010 }
3011 } else {
3012 if timerCheck != nil {
3013 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003014 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303015 }
3016 timerCheck = nil
3017 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303018 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
3019 if dh.heartbeatSignature == 0 {
3020 // First time the signature will be 0, update the signture to DB when not found.
3021 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
3022 dh.heartbeatSignature = heartBeat.HeartbeatSignature
3023 }
3024 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
3025
3026 dh.lockDevice.RLock()
3027 // Stop the read indication only if it the routine is active
3028 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3029 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3030 // on next execution of the readIndication routine.
3031 if !dh.isReadIndicationRoutineActive {
3032 // Start reading indications
3033 go func() {
3034 if err = dh.readIndications(ctx); err != nil {
3035 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3036 }
3037 }()
3038 }
3039 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303040 } else {
3041 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
Sridhar Ravindrab60d0042026-02-04 11:39:15 +05303042 go dh.updateStateRebooted(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303043 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
3044 dh.heartbeatSignature = heartBeat.HeartbeatSignature
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303045 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303046 }
3047 cancel()
3048 case <-dh.stopHeartbeatCheck:
balaji.nagarajan8f95de32026-02-01 11:39:44 +05303049 logger.Infow(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303050 return
3051 }
3052 }
3053}
3054
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003055func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04003056 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003057 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07003058 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3059 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3060 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3061 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3062 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003063 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07003064 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3065 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003066 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303067
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303068 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003069 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003070 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04003071 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04003072 DeviceId: dh.device.Id,
3073 OperStatus: voltha.OperStatus_UNKNOWN,
3074 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
3075 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003076 _ = 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 -04003077 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303078 /*
3079 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
3080 DeviceId: dh.device.Id,
3081 PortTypeFilter: 0,
3082 OperStatus: voltha.OperStatus_UNKNOWN,
3083 }); err != nil {
3084 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3085 }
3086 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003087
Akash Kankanala041a2122024-10-16 15:49:22 +05303088 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003089 raisedTs := time.Now().Unix()
bseeniva0b9cbcb2026-02-12 19:11:11 +05303090 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3091 device.OperStatus = voltha.OperStatus_UNKNOWN
3092 dh.device = device // update local copy of the device
3093 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003094
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003095 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003096 // Stop the Stats collector
3097 if dh.isCollectorActive {
3098 dh.stopCollector <- true
3099 }
3100 // stop the heartbeat check routine
3101 if dh.isHeartbeatCheckActive {
3102 dh.stopHeartbeatCheck <- true
3103 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003104 // Stop the read indication only if it the routine is active
3105 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3106 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3107 // on next execution of the readIndication routine.
3108 if dh.isReadIndicationRoutineActive {
3109 dh.stopIndications <- true
3110 }
3111 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003112 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303113 }
3114}
kesavand39e0aa32020-01-28 20:58:50 -05003115
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303116func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3117 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3118 if err != nil || device == nil {
3119 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3120 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3121 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3122 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3123 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3124 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3125 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3126 return
3127 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303128 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003129 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303130
3131 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3132 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303133 // First, stop the read indication and heartbeat check routines to prevent any delay
3134 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303135 dh.lockDevice.RLock()
3136 // Stop the read indication only if it the routine is active
3137 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3138 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3139 // on next execution of the readIndication routine.
3140 if dh.isReadIndicationRoutineActive {
3141 dh.stopIndications <- true
3142 }
balaji.nagarajanc7503512026-02-04 09:47:43 +05303143
3144 // stop the heartbeat check routine
3145 if dh.isHeartbeatCheckActive {
3146 dh.stopHeartbeatCheck <- true
3147 }
3148
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303149 dh.lockDevice.RUnlock()
3150
bseenivad1c984b2025-01-09 12:54:44 +05303151 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3152 DeviceId: dh.device.Id,
3153 OperStatus: voltha.OperStatus_REBOOTED,
3154 ConnStatus: voltha.ConnectStatus_REACHABLE,
3155 }); err != nil {
3156 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3157 }
3158
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303159 //raise olt communication failure event
3160 raisedTs := time.Now().Unix()
bseeniva0b9cbcb2026-02-12 19:11:11 +05303161 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3162 device.OperStatus = voltha.OperStatus_UNKNOWN
3163 dh.device = device // update local copy of the device
3164 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303165
Gustavo Silva41af9122022-10-11 11:05:13 -03003166 if err := dh.cleanupDeviceResources(ctx); err != nil {
3167 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3168 } else {
3169 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3170 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003171
3172 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303173 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003174 if dh.isCollectorActive {
3175 dh.stopCollector <- true
3176 }
balaji.nagarajanc7503512026-02-04 09:47:43 +05303177
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003178 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303179
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003180 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303181
Akash Kankanala041a2122024-10-16 15:49:22 +05303182 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303183 dh.adapterPreviouslyConnected = false
3184 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303185 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3186 if err != nil || childDevices == nil {
3187 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3188 continue
3189 }
3190 if len(childDevices.Items) == 0 {
3191 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3192 break
3193 } else {
3194 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3195 time.Sleep(5 * time.Second)
3196 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303197 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303198 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003199 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303200 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3201 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303202}
3203
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303204// EnableOnuSerialNumber to enable onu serial number
3205func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3206 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3207 onuSerialNumber := device.SerialNumber
3208
3209 // fetch interfaceid from PortNo
3210 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3211
3212 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3213 if err != nil {
3214 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3215 log.Fields{
3216 "devicer-id": dh.device.Id,
3217 "serial-number": onuSerialNumber}, err).Log()
3218 }
3219
3220 onuIntf := &oop.InterfaceOnuSerialNumber{
3221 IntfId: ponID,
3222 OnuSerialNumber: sn,
3223 }
3224 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3225
3226 if err != nil {
3227 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3228 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3229 "device-id": dh.device.Id,
3230 "onu-serial-number": onuSerialNumber}, err)
3231 }
3232 return nil
3233}
3234
3235// DisableOnuSerialNumber to disable onu serial number
3236func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3237 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3238 onuSerialNumber := device.SerialNumber
3239 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3240 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3241 if err != nil {
3242 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3243 log.Fields{
3244 "devicer-id": dh.device.Id,
3245 "serial-number": onuSerialNumber}, err).Log()
3246 }
3247
3248 onuIntf := &oop.InterfaceOnuSerialNumber{
3249 OnuSerialNumber: sn,
3250 IntfId: ponID,
3251 }
3252 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3253
3254 if err != nil {
3255 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3256 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3257 "device-id": dh.device.Id,
3258 "onu-serial-number": onuSerialNumber}, err)
3259 }
3260 return nil
3261}
3262
3263// EnableOnu to enable onu
3264func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3265 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3266 onuSerialNumber := device.SerialNumber
3267 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3268 if InCacheOnuDev == nil {
3269 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3270 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3271 "device-id": dh.device.Id,
3272 "onu-serial-number": onuSerialNumber}, nil)
3273 }
3274 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})
3275
3276 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3277 if err != nil {
3278 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3279 log.Fields{
3280 "device-id": dh.device.Id,
3281 "serial-number": onuSerialNumber}, err).Log()
3282 }
3283
3284 onuIntf := &oop.InterfaceOnuSerialNumber{
3285 OnuSerialNumber: sn,
3286 IntfId: InCacheOnuDev.intfID,
3287 }
3288 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3289 OnuId: InCacheOnuDev.onuID,
3290 IntfIdSerialNum: onuIntf,
3291 }
3292 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3293
3294 if err != nil {
3295 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3296 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3297 "olt-device-id": dh.device.Id,
3298 "onu-serial-number": onuSerialNumber}, err)
3299 }
3300 return nil
3301}
3302
3303// DisableOnu to disable onu
3304func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3305 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3306 onuSerialNumber := device.SerialNumber
3307 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3308 if InCacheOnuDev == nil {
3309 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3310 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3311 "device-id": dh.device.Id,
3312 "onu-serial-number": onuSerialNumber}, nil)
3313 }
3314 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})
3315
3316 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3317 if err != nil {
3318 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3319 log.Fields{
3320 "device-id": dh.device.Id,
3321 "serial-number": onuSerialNumber}, err).Log()
3322 }
3323
3324 onuIntf := &oop.InterfaceOnuSerialNumber{
3325 OnuSerialNumber: sn,
3326 IntfId: InCacheOnuDev.intfID,
3327 }
3328 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3329 OnuId: InCacheOnuDev.onuID,
3330 IntfIdSerialNum: onuIntf,
3331 }
3332 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3333
3334 if err != nil {
3335 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3336 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3337 "olt-device-id": dh.device.Id,
3338 "onu-serial-number": onuSerialNumber}, err)
3339 }
3340 return nil
3341}
3342
kesavand39e0aa32020-01-28 20:58:50 -05003343// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003344func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3345 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3346 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003347}
3348
3349// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003350func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3351 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3352 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003353}
3354
Mahir Gunyela2e68702022-12-07 00:00:42 -08003355// 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 +00003356func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3357 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003358 if port.GetType() == voltha.Port_ETHERNET_NNI {
3359 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003360 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303361 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303362 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003363 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003364 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003365 }
3366 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003367 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003368 ponIntf := &oop.Interface{IntfId: ponID}
3369 var operStatus voltha.OperStatus_Types
bseenivaa1622112025-12-11 18:24:02 +05303370 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
kesavand39e0aa32020-01-28 20:58:50 -05003371 if enablePort {
3372 operStatus = voltha.OperStatus_ACTIVE
bseenivaa1622112025-12-11 18:24:02 +05303373 out, err := dh.Client.EnablePonIf(subCtx, ponIntf)
3374 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003375 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303376 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003377 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003378 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003379 }
3380 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003381 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003382 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003383 } else {
3384 operStatus = voltha.OperStatus_UNKNOWN
bseenivaa1622112025-12-11 18:24:02 +05303385 out, err := dh.Client.DisablePonIf(subCtx, ponIntf)
3386 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003387 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303388 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003389 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003390 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003391 }
3392 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003393 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003394 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003395 }
khenaidoodc2116e2021-10-19 17:33:19 -04003396 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003397 DeviceId: dh.device.Id,
3398 PortType: voltha.Port_PON_OLT,
3399 PortNo: port.PortNo,
3400 OperStatus: operStatus,
3401 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303402 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303403 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003404 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003405 }
3406 return nil
3407}
3408
Mahir Gunyela2e68702022-12-07 00:00:42 -08003409// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003410func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003411 // Disable the port and update the oper_port_status to core
3412 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003413 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003414 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003415 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303416 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303417 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003418 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003419 }
3420 }
3421 }
3422 return nil
3423}
3424
Mahir Gunyela2e68702022-12-07 00:00:42 -08003425// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003426func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3427 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3428 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003429 if port.Type == voltha.Port_ETHERNET_NNI {
3430 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003431 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003432 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003433 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003434 }
3435 }
3436 if port.Type == voltha.Port_PON_OLT {
3437 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003438 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003439 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003440 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003441 }
3442 }
3443 }
3444}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003445
3446// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003447func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003448 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003449 if dh.getDeviceDeletionInProgressFlag() {
3450 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3451 // will reboot, so everything will be reset on the pOLT too.
3452 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3453 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3454 return nil
3455 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303456
3457 if dh.transitionMap.currentDeviceState != deviceStateUp {
3458 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})
3459 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3460 }
3461
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003462 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003463 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003464
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003465 var sn *oop.SerialNumber
3466 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003467 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303468 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003469 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303470 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003471 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003472 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003473
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003474 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303475 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003476 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003477 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3478 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3479 "device-id": dh.device.Id,
3480 "intf-id": intfID,
3481 "onuID": onuID,
3482 "err": err})
3483 } else {
3484 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003485 // Delete flows from device before schedulers and queue
3486 // Clear flowids for gem cache.
3487 removedFlows := []uint64{}
3488 for _, gem := range onuGem.GemPorts {
3489 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3490 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303491 // multiple gem port can have the same flow id
3492 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003493 var alreadyRemoved bool
3494 for _, removedFlowID := range removedFlows {
3495 if removedFlowID == flowID {
3496 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3497 alreadyRemoved = true
3498 break
3499 }
3500 }
3501 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003502 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003503 removedFlows = appendUnique64bit(removedFlows, flowID)
3504 }
3505 }
3506 }
3507 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3508 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003509 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3510 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3511 "device-id": dh.device.Id,
3512 "onu-device": onu,
3513 "err": err})
3514 }
yasin saplibddc2d72022-02-08 13:10:17 +00003515 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003516 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3517 "intf-id": intfID,
3518 "onu-device": onu,
3519 "onu-gem": onuGem,
3520 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303521 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003522 }
3523 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003524 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003525
bseenivaa1622112025-12-11 18:24:02 +05303526 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003527 // Now clear the ONU on the OLT
bseenivaa1622112025-12-11 18:24:02 +05303528 if _, err := dh.Client.DeleteOnu(subCtx, onu); err != nil {
3529 cancel()
Thomas Lee S94109f12020-03-03 16:39:29 +05303530 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303531 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003532 "onu-id": onuID}, err).Log()
3533 }
bseenivaa1622112025-12-11 18:24:02 +05303534 cancel()
balaji.nagarajanbf44ce82026-01-27 08:59:36 +05303535
3536 //free resources only if the deleteonu is successful
3537 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
3538 dh.onus.Delete(onuKey)
3539 dh.discOnus.Delete(onuSn)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003540 return nil
3541}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003542func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3543 flow := &oop.Flow{FlowId: flowID}
3544 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3545 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3546 "device-id": dh.device.Id})
3547 } else {
3548 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3549 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3550 "device-id": dh.device.Id,
3551 "err": err})
3552 }
3553 }
3554}
Girish Gowdracefae192020-03-19 18:14:10 -07003555
3556func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003557 for _, field := range flow_utils.GetOfbFields(flow) {
3558 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003559 return field.GetPort()
3560 }
3561 }
3562 return InvalidPort
3563}
3564
3565func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003566 for _, action := range flow_utils.GetActions(flow) {
3567 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003568 if out := action.GetOutput(); out != nil {
3569 return out.GetPort()
3570 }
3571 }
3572 }
3573 return InvalidPort
3574}
3575
Girish Gowdracefae192020-03-19 18:14:10 -07003576func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3577 inPort := getInPortFromFlow(flow)
3578 outPort := getOutPortFromFlow(flow)
3579
3580 if inPort == InvalidPort || outPort == InvalidPort {
3581 return inPort, outPort
3582 }
3583
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003584 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003585 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003586 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003587 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003588 return uniPort, outPort
3589 }
3590 }
3591 } else {
3592 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003593 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003594 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003595 return inPort, uniPort
3596 }
3597 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003598 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003599 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003600 return uniPort, outPort
3601 }
3602 }
3603 }
3604
3605 return InvalidPort, InvalidPort
3606}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003607
3608func extractOmciTransactionID(omciPkt []byte) uint16 {
3609 if len(omciPkt) > 3 {
3610 d := omciPkt[0:2]
3611 transid := binary.BigEndian.Uint16(d)
3612 return transid
3613 }
3614 return 0
3615}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003616
3617// StoreOnuDevice stores the onu parameters to the local cache.
3618func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3619 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3620 dh.onus.Store(onuKey, onuDevice)
3621}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003622
khenaidoodc2116e2021-10-19 17:33:19 -04003623func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003624 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003625 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003626 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003627 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003628 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003629 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003630 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003631 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3632 return nil, err
3633 }
3634 ID = device.ProxyAddress.GetOnuId()
3635 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3636 valueparam.Onu = &Onu
3637 valueparam.Value = value
3638
3639 // This API is unsupported until agent patch is added
3640 resp.Unsupported = uint32(value)
3641 _ = ctx
3642
3643 // Uncomment this code once agent changes are complete and tests
3644 /*
3645 resp, err = dh.Client.GetValue(ctx, valueparam)
3646 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003647 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003648 return nil, err
3649 }
3650 */
3651
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003652 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 -08003653 return resp, nil
3654}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003655
Akash Kankanala041a2122024-10-16 15:49:22 +05303656func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003657 // Default to NNI
3658 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003659 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003660 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003661 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003662 }
3663 return intfID
3664}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003665
Akash Kankanala041a2122024-10-16 15:49:22 +05303666func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003667 dh.perPonOnuIndicationChannelLock.Lock()
3668 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3669 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003670 return ch.indicationChannel
3671 }
3672 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303673 // We create a buffered channel here to avoid calling function to be blocked
3674 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003675 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003676 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003677 stopChannel: make(chan struct{}),
3678 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003679 dh.perPonOnuIndicationChannel[intfID] = channels
3680 dh.perPonOnuIndicationChannelLock.Unlock()
3681 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003682 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003683}
3684
Mahir Gunyelb0046752021-02-26 13:51:05 -08003685func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3686 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3687 dh.perPonOnuIndicationChannelLock.Lock()
3688 defer dh.perPonOnuIndicationChannelLock.Unlock()
3689 for _, v := range dh.perPonOnuIndicationChannel {
3690 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003691 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003692 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003693}
3694
Mahir Gunyelb0046752021-02-26 13:51:05 -08003695func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3696 ind := onuIndicationMsg{
3697 ctx: ctx,
3698 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003699 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003700 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003701 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303702 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003703}
3704
Mahir Gunyelb0046752021-02-26 13:51:05 -08003705func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003706 for {
3707 select {
3708 // process one indication per onu, before proceeding to the next one
3709 case onuInd := <-onuChannels.indicationChannel:
bseeniva0b9cbcb2026-02-12 19:11:11 +05303710 indication := onuInd.indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003711 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
bseeniva0b9cbcb2026-02-12 19:11:11 +05303712 "ind": indication.String()})
Andrea Campanella46b01402021-11-15 16:58:05 -08003713 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003714 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003715 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003716 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3717 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003718 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003719 }
3720 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003721 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003722 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3723 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003724 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003725 }
3726 }
3727 case <-onuChannels.stopChannel:
3728 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3729 close(onuChannels.indicationChannel)
3730 return
3731 }
3732 }
3733}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003734
3735// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3736// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003737func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003738 if dh.getDeviceDeletionInProgressFlag() {
3739 // The device itself is going to be reset as part of deletion. So nothing to be done.
3740 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3741 return nil
3742 }
3743
Girish Gowdra491a9c62021-01-06 16:43:07 -08003744 // Step1 : Fill McastFlowOrGroupControlBlock
3745 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3746 // Step3 : Wait on response channel for response
3747 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003748 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003749 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3750 errChan := make(chan error)
3751 var groupID uint32
3752 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3753 ctx: ctx,
3754 flowOrGroupAction: action,
3755 flow: flow,
3756 group: group,
3757 errChan: &errChan,
3758 }
3759 if flow != nil {
3760 groupID = flow_utils.GetGroup(flow)
3761 } else if group != nil {
3762 groupID = group.Desc.GroupId
3763 } else {
3764 return errors.New("flow-and-group-both-nil")
3765 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003766 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3767 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3768 // Derive the appropriate go routine to handle the request by a simple module operation.
3769 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3770 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3771 // Wait for handler to return error value
3772 err := <-errChan
3773 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3774 return err
3775 }
3776 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3777 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003778}
3779
3780// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003781func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003782 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003783 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003784 // block on the channel to receive an incoming mcast flow/group
3785 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003786 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3787 if mcastFlowOrGroupCb.flow != nil {
3788 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3789 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3790 log.Fields{"device-id": dh.device.Id,
3791 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003792 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3793 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3794 for _, flMgr := range dh.flowMgr {
3795 if flMgr != nil {
3796 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3797 break
3798 }
3799 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003800 // Pass the return value over the return channel
3801 *mcastFlowOrGroupCb.errChan <- err
3802 } else { // flow remove
3803 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3804 log.Fields{"device-id": dh.device.Id,
3805 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003806 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3807 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3808 for _, flMgr := range dh.flowMgr {
3809 if flMgr != nil {
3810 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3811 break
3812 }
3813 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003814 // Pass the return value over the return channel
3815 *mcastFlowOrGroupCb.errChan <- err
3816 }
3817 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303818 switch mcastFlowOrGroupCb.flowOrGroupAction {
3819 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003820 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3821 log.Fields{"device-id": dh.device.Id,
3822 "groupToAdd": mcastFlowOrGroupCb.group})
3823 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3824 // Pass the return value over the return channel
3825 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303826 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003827 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3828 log.Fields{"device-id": dh.device.Id,
3829 "groupToModify": mcastFlowOrGroupCb.group})
3830 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3831 // Pass the return value over the return channel
3832 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303833 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003834 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3835 log.Fields{"device-id": dh.device.Id,
3836 "groupToRemove": mcastFlowOrGroupCb.group})
3837 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3838 // Pass the return value over the return channel
3839 *mcastFlowOrGroupCb.errChan <- err
3840 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003841 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003842 case <-stopHandler:
3843 dh.mcastHandlerRoutineActive[routineIndex] = false
3844 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003845 }
3846 }
3847}
kesavand62126212021-01-12 04:56:06 -05003848
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003849// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003850func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003851 for i, v := range dh.stopMcastHandlerRoutine {
3852 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003853 select {
3854 case v <- true:
3855 case <-time.After(time.Second * 5):
3856 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3857 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003858 }
3859 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003860
3861 if dh.incomingMcastFlowOrGroup != nil {
3862 for k := range dh.incomingMcastFlowOrGroup {
3863 if dh.incomingMcastFlowOrGroup[k] != nil {
3864 dh.incomingMcastFlowOrGroup[k] = nil
3865 }
3866 }
3867 dh.incomingMcastFlowOrGroup = nil
3868 }
3869
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003870 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003871 logger.Debug(ctx, "stopped all mcast handler routines")
3872}
3873
Akash Kankanala041a2122024-10-16 15:49:22 +05303874// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003875func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003876 singleValResp := extension.SingleGetValueResponse{
3877 Response: &extension.GetValueResponse{
3878 Response: &extension.GetValueResponse_PortCoutners{
3879 PortCoutners: &extension.GetOltPortCountersResponse{},
3880 },
3881 },
3882 }
3883
Akash Kankanala041a2122024-10-16 15:49:22 +05303884 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003885 return &extension.SingleGetValueResponse{
3886 Response: &extension.GetValueResponse{
3887 Status: status,
3888 ErrReason: reason,
3889 },
3890 }
3891 }
3892
3893 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3894 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303895 // send error response
kesavand62126212021-01-12 04:56:06 -05003896 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3897 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3898 }
3899 statIndChn := make(chan bool, 1)
3900 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3901 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303902 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003903
3904 go func() {
bseenivaa1622112025-12-11 18:24:02 +05303905 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3906 _, err := dh.Client.CollectStatistics(subCtx, new(oop.Empty))
kesavand62126212021-01-12 04:56:06 -05003907 if err != nil {
3908 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3909 }
bseenivaa1622112025-12-11 18:24:02 +05303910 cancel()
kesavand62126212021-01-12 04:56:06 -05003911 }()
3912 select {
3913 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303914 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003915 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3916 case <-time.After(oltPortInfoTimeout * time.Second):
3917 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3918 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3919 case <-ctx.Done():
3920 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3921 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3922 }
mgouda86543582025-10-29 20:58:16 +05303923 switch oltPortInfo.PortType {
3924 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303925 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003926 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003927 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3928 cmnni := dh.portStats.collectNNIMetrics(intfID)
3929 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303930 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003931 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3932 }
3933 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3934 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303935 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003936 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003937 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003938 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3939 cmpon := dh.portStats.collectPONMetrics(intfID)
3940 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303941 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003942 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3943 }
3944 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3945 return &singleValResp
3946 }
3947 }
3948 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3949}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303950
Akash Kankanala041a2122024-10-16 15:49:22 +05303951//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303952func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303953 singleValResp := extension.SingleGetValueResponse{
3954 Response: &extension.GetValueResponse{
3955 Status: extension.GetValueResponse_OK,
3956 Response: &extension.GetValueResponse_OffloadedAppsStats{
3957 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3958 },
3959 },
3960 }
3961
3962 return &singleValResp
3963}
3964
Akash Kankanala041a2122024-10-16 15:49:22 +05303965//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303966func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303967 singleValResp := extension.SingleSetValueResponse{
3968 Response: &extension.SetValueResponse{
3969 Status: extension.SetValueResponse_OK,
3970 },
3971 }
3972
3973 return &singleValResp
3974}
3975
Akash Kankanala041a2122024-10-16 15:49:22 +05303976//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303977func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303978 singleValResp := extension.SingleSetValueResponse{
3979 Response: &extension.SetValueResponse{
3980 Status: extension.SetValueResponse_OK,
3981 },
3982 }
3983
3984 return &singleValResp
3985}
3986
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303987func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303988 singleValResp := extension.SingleGetValueResponse{
3989 Response: &extension.GetValueResponse{
3990 Response: &extension.GetValueResponse_OnuPonCounters{
3991 OnuPonCounters: &extension.GetOnuCountersResponse{},
3992 },
3993 },
3994 }
3995
Akash Kankanala041a2122024-10-16 15:49:22 +05303996 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303997 return &extension.SingleGetValueResponse{
3998 Response: &extension.GetValueResponse{
3999 Status: status,
4000 ErrReason: reason,
4001 },
4002 }
4003 }
4004 intfID := onuPonInfo.IntfId
4005 onuID := onuPonInfo.OnuId
4006 onuKey := dh.formOnuKey(intfID, onuID)
4007
4008 if _, ok := dh.onus.Load(onuKey); !ok {
4009 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
4010 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4011 }
4012 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
4013 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
4014 if cmnni == nil {
4015 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4016 }
4017 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
4018 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05304019}
Gamze Abaka85e9a142021-05-26 13:41:39 +00004020
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304021func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
4022 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
4023 if err != nil {
4024 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
4025 return nil, err
4026 }
4027 if onuGemInfo != nil {
4028 if len(onuGemInfo.UniPorts) == 0 {
4029 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
4030 return nil, err
4031 }
4032 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
4033 return onuGemInfo, nil
4034 }
4035 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
4036 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
4037}
4038
4039func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
4040 var err error
4041 var allocStats *oop.OnuAllocIdStatistics
4042 var onuGemStats *oop.GemPortStatistics
4043 for _, uni := range onuGemInfo.UniPorts {
4044 uniID := plt.UniIDFromPortNum(uni)
4045 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
4046 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
4047 if len(tpIDs) == 0 {
4048 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
4049 continue
4050 }
4051 for _, tpId := range tpIDs {
4052 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
4053 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
4054 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
4055 if techProfileInstance != nil {
4056 switch tpInst := techProfileInstance.(type) {
4057 case *tp_pb.TechProfileInstance:
4058 allocId := tpInst.UsScheduler.AllocId
4059 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
bseenivaa1622112025-12-11 18:24:02 +05304060 allocCtx, allocCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4061 allocStats, err = dh.Client.GetAllocIdStatistics(allocCtx, &onuAllocPkt)
4062 allocCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304063 if err != nil {
4064 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
4065 return err
4066 }
4067 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
4068 allocIdInfo.AllocId = allocStats.AllocId
4069 allocIdInfo.RxBytes = allocStats.RxBytes
4070
4071 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
4072
4073 gemPorts := tpInst.UpstreamGemPortAttributeList
4074 for _, gem := range gemPorts {
4075 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
bseenivaa1622112025-12-11 18:24:02 +05304076 gemCtx, gemCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4077 onuGemStats, err = dh.Client.GetGemPortStatistics(gemCtx, &onuGemPkt)
4078 gemCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304079 if err != nil {
4080 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
4081 return err
4082 }
4083 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
4084 gemStatsInfo.GemId = onuGemStats.GemportId
4085 gemStatsInfo.RxBytes = onuGemStats.RxBytes
4086 gemStatsInfo.RxPackets = onuGemStats.RxPackets
4087 gemStatsInfo.TxBytes = onuGemStats.TxBytes
4088 gemStatsInfo.TxPackets = onuGemStats.TxPackets
4089
4090 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
4091 }
4092 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
4093
4094 default:
4095 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4096 return err
4097 }
4098 } else {
4099 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4100 continue
4101 }
4102 }
4103 }
4104 return err
4105}
4106
4107//nolint:unparam
4108func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4109 singleValResp := extension.SingleGetValueResponse{
4110 Response: &extension.GetValueResponse{
4111 Status: extension.GetValueResponse_OK,
4112 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4113 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4114 },
4115 },
4116 }
4117 errResp := func(status extension.GetValueResponse_Status,
4118 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4119 return &extension.SingleGetValueResponse{
4120 Response: &extension.GetValueResponse{
4121 Status: status,
4122 ErrReason: reason,
4123 },
4124 }
4125 }
4126
4127 var intfID, onuID uint32
4128 if onuDevice != nil {
4129 onuID = onuDevice.ProxyAddress.OnuId
4130 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4131 }
4132
4133 onuKey := dh.formOnuKey(intfID, onuID)
4134 if _, ok := dh.onus.Load(onuKey); !ok {
4135 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4136 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4137 }
4138 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4139
4140 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4141 if err == nil {
4142 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4143 if err != nil {
4144 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4145 }
4146 } else {
4147 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4148 }
4149 return &singleValResp
4150}
4151
nikesh.krishnanc8473432023-06-14 12:14:54 +05304152func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304153 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
bseenivaa1622112025-12-11 18:24:02 +05304154 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4155 OnuInfo, err := dh.Client.GetOnuInfo(subCtx, &Onu)
4156 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304157 if err != nil {
4158 return nil, err
4159 }
4160 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304161}
4162
4163func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304164 Intf := oop.Interface{IntfId: intfID}
bseenivaa1622112025-12-11 18:24:02 +05304165 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4166 IntfInfo, err := dh.Client.GetPonInterfaceInfo(subCtx, &Intf)
4167 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304168 if err != nil {
4169 return nil, err
4170 }
4171 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304172}
4173
Gamze Abaka85e9a142021-05-26 13:41:39 +00004174func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004175 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
bseenivaa1622112025-12-11 18:24:02 +05304176 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4177 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4178 cancel()
Gamze Abaka85e9a142021-05-26 13:41:39 +00004179 if err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05304180 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"intf-id": Onu.IntfId, "onu-id": Onu.OnuId, "err": err})
Gamze Abaka85e9a142021-05-26 13:41:39 +00004181 return generateSingleGetValueErrorResponse(err)
4182 }
4183 return &extension.SingleGetValueResponse{
4184 Response: &extension.GetValueResponse{
4185 Status: extension.GetValueResponse_OK,
4186 Response: &extension.GetValueResponse_RxPower{
4187 RxPower: &extension.GetRxPowerResponse{
4188 IntfId: rxPowerRequest.IntfId,
4189 OnuId: rxPowerRequest.OnuId,
4190 Status: rxPower.Status,
4191 FailReason: rxPower.FailReason.String(),
4192 RxPower: rxPower.RxPowerMeanDbm,
4193 },
4194 },
4195 },
4196 }
4197}
4198
praneeth nalmas55616d62023-02-06 09:19:18 +05304199func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304200 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304201 return &extension.SingleGetValueResponse{
4202 Response: &extension.GetValueResponse{
4203 Status: status,
4204 ErrReason: reason,
4205 },
4206 }
4207 }
4208
4209 resp := extension.SingleGetValueResponse{
4210 Response: &extension.GetValueResponse{
4211 Status: extension.GetValueResponse_OK,
4212 Response: &extension.GetValueResponse_OltRxPower{
4213 OltRxPower: &extension.GetOltRxPowerResponse{},
4214 },
4215 },
4216 }
4217
4218 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4219 portLabel := OltRxPowerRequest.PortLabel
4220 serialNumber := OltRxPowerRequest.OnuSn
4221
4222 portInfo := strings.Split(portLabel, "-")
4223 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4224
4225 if err != nil {
4226 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4227 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4228 }
4229
4230 if portInfo[0] != "pon" {
4231 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4232 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4233 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304234
4235 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304236 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4237 if onuDev != nil {
bseenivaa1622112025-12-11 18:24:02 +05304238 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
praneeth nalmas55616d62023-02-06 09:19:18 +05304239 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
bseenivaa1622112025-12-11 18:24:02 +05304240 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4241 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304242 if err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05304243 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"intf-id": Onu.IntfId, "onu-id": Onu.OnuId, "err": err})
praneeth nalmas55616d62023-02-06 09:19:18 +05304244 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304245 }
4246
4247 rxPowerValue := extension.RxPower{}
4248 rxPowerValue.OnuSn = onuDev.serialNumber
4249 rxPowerValue.Status = rxPower.GetStatus()
4250 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4251 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4252
4253 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304254 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304255 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4256 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4257 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304258 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304259 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304260 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304261 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
bseenivaa1622112025-12-11 18:24:02 +05304262 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4263 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4264 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304265 if err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05304266 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"intf-id": Onu.IntfId, "onu-id": Onu.OnuId, "err": err})
praneeth nalmas55616d62023-02-06 09:19:18 +05304267 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304268 rxPowerValue := extension.RxPower{}
4269 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4270 rxPowerValue.Status = rxPower.GetStatus()
4271 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4272 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4273
4274 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4275 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304276 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05304277 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"status": resp.Response.Status})
praneeth nalmas55616d62023-02-06 09:19:18 +05304278 return true
4279 })
4280 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05304281 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"status": resp.Response.Status})
praneeth nalmas55616d62023-02-06 09:19:18 +05304282 return &resp
4283}
4284
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304285func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4286 errResp := func(status extension.GetValueResponse_Status,
4287 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4288 return &extension.SingleGetValueResponse{
4289 Response: &extension.GetValueResponse{
4290 Status: status,
4291 ErrReason: reason,
4292 },
4293 }
4294 }
4295
4296 resp := extension.SingleGetValueResponse{
4297 Response: &extension.GetValueResponse{
4298 Status: extension.GetValueResponse_OK,
4299 Response: &extension.GetValueResponse_OltPonStatsResponse{
4300 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4301 },
4302 },
4303 }
4304
4305 portLabel := ponStatsRequest.GetPortLabel()
4306 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4307
4308 portInfo := strings.Split(portLabel, "-")
4309 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4310
4311 if err != nil {
4312 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4313 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4314 }
4315
4316 if portInfo[0] != "pon" {
4317 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4318 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4319 }
4320
4321 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304322 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4323 ponStats, err := dh.Client.GetPonPortStatistics(subCtx, &Interface)
4324 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304325 if err != nil {
4326 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4327 return generateSingleGetValueErrorResponse(err)
4328 }
4329
4330 ponPortStats := resp.Response.GetOltPonStatsResponse()
4331 ponPortStats.PonPort = uint32(portNumber)
4332 ponPortStats.PortStatistics = ponStats
4333
bseeniva0b9cbcb2026-02-12 19:11:11 +05304334 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"status": resp.Response.Status, "pon-port": portNumber})
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304335 return &resp
4336}
4337
4338func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4339 errResp := func(status extension.GetValueResponse_Status,
4340 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4341 return &extension.SingleGetValueResponse{
4342 Response: &extension.GetValueResponse{
4343 Status: status,
4344 ErrReason: reason,
4345 },
4346 }
4347 }
4348
4349 resp := extension.SingleGetValueResponse{
4350 Response: &extension.GetValueResponse{
4351 Status: extension.GetValueResponse_OK,
4352 Response: &extension.GetValueResponse_OltNniStatsResponse{
4353 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4354 },
4355 },
4356 }
4357
4358 portLabel := nniStatsRequest.GetPortLabel()
4359 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4360
4361 portInfo := strings.Split(portLabel, "-")
4362 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4363
4364 if err != nil {
4365 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4366 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4367 }
4368
4369 if portInfo[0] != "nni" {
4370 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4371 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4372 }
4373
4374 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304375 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4376 nniStats, err := dh.Client.GetNniPortStatistics(subCtx, &Interface)
4377 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304378 if err != nil {
4379 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4380 return generateSingleGetValueErrorResponse(err)
4381 }
4382
4383 nniPortStats := resp.Response.GetOltNniStatsResponse()
4384 nniPortStats.NniPort = uint32(portNumber)
4385 nniPortStats.PortStatistics = nniStats
4386
bseeniva0b9cbcb2026-02-12 19:11:11 +05304387 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"status": resp.Response.Status, "nni-port": portNumber})
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304388 return &resp
4389}
4390
Akash Kankanala041a2122024-10-16 15:49:22 +05304391// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004392func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304393 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004394 return &extension.SingleGetValueResponse{
4395 Response: &extension.GetValueResponse{
4396 Status: status,
4397 ErrReason: reason,
4398 },
4399 }
4400 }
4401
4402 if err != nil {
4403 if e, ok := status.FromError(err); ok {
4404 switch e.Code() {
4405 case codes.Internal:
4406 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4407 case codes.DeadlineExceeded:
4408 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4409 case codes.Unimplemented:
4410 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4411 case codes.NotFound:
4412 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4413 }
4414 }
4415 }
4416
4417 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4418}
khenaidoo106c61a2021-08-11 18:05:46 -04004419
4420/*
4421Helper functions to communicate with Core
4422*/
4423
4424func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4425 cClient, err := dh.coreClient.GetCoreServiceClient()
4426 if err != nil || cClient == nil {
4427 return nil, err
4428 }
4429 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4430 defer cancel()
4431 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4432}
4433
khenaidoodc2116e2021-10-19 17:33:19 -04004434func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004435 cClient, err := dh.coreClient.GetCoreServiceClient()
4436 if err != nil || cClient == nil {
4437 return nil, err
4438 }
4439 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4440 defer cancel()
4441 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4442}
4443
khenaidoodc2116e2021-10-19 17:33:19 -04004444func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004445 cClient, err := dh.coreClient.GetCoreServiceClient()
4446 if err != nil || cClient == nil {
4447 return err
4448 }
4449 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4450 defer cancel()
4451 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4452 return err
4453}
4454
4455func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4456 cClient, err := dh.coreClient.GetCoreServiceClient()
4457 if err != nil || cClient == nil {
4458 return nil, err
4459 }
4460 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4461 defer cancel()
4462 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4463}
4464
4465func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4466 cClient, err := dh.coreClient.GetCoreServiceClient()
4467 if err != nil || cClient == nil {
4468 return nil, err
4469 }
4470 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4471 defer cancel()
4472 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4473}
4474
4475func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4476 cClient, err := dh.coreClient.GetCoreServiceClient()
4477 if err != nil || cClient == nil {
4478 return err
4479 }
4480 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4481 defer cancel()
4482 _, err = cClient.DeviceUpdate(subCtx, device)
4483 return err
4484}
4485
khenaidoodc2116e2021-10-19 17:33:19 -04004486func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004487 cClient, err := dh.coreClient.GetCoreServiceClient()
4488 if err != nil || cClient == nil {
4489 return nil, err
4490 }
4491 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4492 defer cancel()
4493 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4494}
4495
khenaidoodc2116e2021-10-19 17:33:19 -04004496func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004497 cClient, err := dh.coreClient.GetCoreServiceClient()
4498 if err != nil || cClient == nil {
4499 return err
4500 }
4501 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4502 defer cancel()
4503 _, err = cClient.SendPacketIn(subCtx, pkt)
4504 return err
4505}
4506
4507func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4508 cClient, err := dh.coreClient.GetCoreServiceClient()
4509 if err != nil || cClient == nil {
4510 return err
4511 }
4512 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4513 defer cancel()
4514 _, err = cClient.PortCreated(subCtx, port)
4515 return err
4516}
4517
khenaidoodc2116e2021-10-19 17:33:19 -04004518func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004519 cClient, err := dh.coreClient.GetCoreServiceClient()
4520 if err != nil || cClient == nil {
4521 return err
4522 }
4523 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4524 defer cancel()
4525 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4526 return err
4527}
4528
khenaidoodc2116e2021-10-19 17:33:19 -04004529func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004530 cClient, err := dh.coreClient.GetCoreServiceClient()
4531 if err != nil || cClient == nil {
4532 return err
4533 }
4534 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4535 defer cancel()
4536 _, err = cClient.PortStateUpdate(subCtx, portState)
4537 return err
4538}
4539
khenaidoodc2116e2021-10-19 17:33:19 -04004540func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004541 cClient, err := dh.coreClient.GetCoreServiceClient()
4542 if err != nil || cClient == nil {
4543 return nil, err
4544 }
4545 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4546 defer cancel()
4547 return cClient.GetDevicePort(subCtx, portFilter)
4548}
4549
nikesh.krishnanc8473432023-06-14 12:14:54 +05304550func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4551 cClient, err := dh.coreClient.GetCoreServiceClient()
4552 if err != nil || cClient == nil {
4553 return nil, err
4554 }
4555 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4556 defer cancel()
4557 return cClient.GetPorts(subCtx, portFilter)
4558}
4559
khenaidoo106c61a2021-08-11 18:05:46 -04004560/*
4561Helper functions to communicate with child adapter
4562*/
4563
khenaidoodc2116e2021-10-19 17:33:19 -04004564func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004565 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4566 if err != nil || aClient == nil {
4567 return err
4568 }
4569 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4570 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4571 defer cancel()
4572 _, err = aClient.OmciIndication(subCtx, response)
4573 return err
4574}
4575
khenaidoodc2116e2021-10-19 17:33:19 -04004576func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004577 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4578 if err != nil || aClient == nil {
4579 return err
4580 }
4581 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4582 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4583 defer cancel()
4584 _, err = aClient.OnuIndication(subCtx, onuInd)
4585 return err
4586}
4587
khenaidoodc2116e2021-10-19 17:33:19 -04004588func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004589 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4590 if err != nil || aClient == nil {
4591 return err
4592 }
4593 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4594 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4595 defer cancel()
4596 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4597 return err
4598}
4599
khenaidoodc2116e2021-10-19 17:33:19 -04004600func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004601 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4602 if err != nil || aClient == nil {
4603 return err
4604 }
4605 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4606 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4607 defer cancel()
4608 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4609 return err
4610}
4611
khenaidoodc2116e2021-10-19 17:33:19 -04004612func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004613 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4614 if err != nil || aClient == nil {
4615 return err
4616 }
4617 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4618 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4619 defer cancel()
4620 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4621 return err
4622}
4623
4624/*
4625Helper functions for remote communication
4626*/
4627
4628// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4629// supports is deleted
4630func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05304631 logger.Debugw(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004632
4633 dh.lockChildAdapterClients.Lock()
4634 defer dh.lockChildAdapterClients.Unlock()
4635 if _, ok := dh.childAdapterClients[endpoint]; ok {
4636 // Already set
4637 return nil
4638 }
4639
4640 // Setup child's adapter grpc connection
4641 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004642 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4643 dh.cfg.AdapterEndpoint,
4644 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004645 "onu_inter_adapter_service.OnuInterAdapterService",
4646 dh.onuInterAdapterRestarted,
4647 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004648 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4649 return err
4650 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304651 retryCodes := []codes.Code{
4652 codes.Unavailable, // server is currently unavailable
4653 codes.DeadlineExceeded, // deadline for the operation was exceeded
4654 }
4655 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4656 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 -04004657
nikesh.krishnand9812542023-08-01 18:31:39 +05304658 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004659 // Wait until we have a connection to the child adapter.
4660 // Unlimited retries or until context expires
4661 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4662 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4663 for {
4664 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4665 if err == nil && client != nil {
4666 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4667 break
4668 }
4669 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4670 // Backoff
4671 if err = backoff.Backoff(subCtx); err != nil {
4672 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4673 break
4674 }
4675 }
4676 return nil
4677}
4678
khenaidoodc2116e2021-10-19 17:33:19 -04004679func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004680 // First check from cache
4681 dh.lockChildAdapterClients.RLock()
4682 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4683 dh.lockChildAdapterClients.RUnlock()
4684 return cgClient.GetOnuInterAdapterServiceClient()
4685 }
4686 dh.lockChildAdapterClients.RUnlock()
4687
4688 // Set the child connection - can occur on restarts
4689 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4690 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4691 cancel()
4692 if err != nil {
4693 return nil, err
4694 }
4695
4696 // Get the child client now
4697 dh.lockChildAdapterClients.RLock()
4698 defer dh.lockChildAdapterClients.RUnlock()
4699 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4700 return cgClient.GetOnuInterAdapterServiceClient()
4701 }
4702 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4703}
4704
4705func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4706 dh.lockChildAdapterClients.Lock()
4707 defer dh.lockChildAdapterClients.Unlock()
4708 for key, client := range dh.childAdapterClients {
4709 client.Stop(ctx)
4710 delete(dh.childAdapterClients, key)
4711 }
4712}
4713
khenaidooefff76e2021-12-15 16:51:30 -05004714// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4715func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4716 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004717 return nil
4718}
4719
khenaidooefff76e2021-12-15 16:51:30 -05004720// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4721func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4722 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004723 return nil
4724 }
khenaidooefff76e2021-12-15 16:51:30 -05004725 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004726}
Girish Gowdra950326e2021-11-05 12:43:24 -07004727
4728func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4729 dh.lockDevice.Lock()
4730 defer dh.lockDevice.Unlock()
4731 dh.isDeviceDeletionInProgress = flag
4732}
4733
4734func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4735 dh.lockDevice.RLock()
4736 defer dh.lockDevice.RUnlock()
4737 return dh.isDeviceDeletionInProgress
4738}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004739
4740// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4741// Returns false if waiting timed out.
4742func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4743 c := make(chan struct{})
4744 go func() {
4745 defer close(c)
4746 wg.Wait()
4747 }()
4748 select {
4749 case <-c:
4750 return true // completed normally
4751 case <-time.After(timeout):
4752 return false // timed out
4753 }
4754}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304755
4756func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4757 val, err := json.Marshal(signature)
4758 if err != nil {
4759 logger.Error(ctx, "failed-to-marshal")
4760 return
4761 }
4762 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4763 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4764 }
4765}
4766
4767func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4768 var signature uint32
4769
4770 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4771 if er == nil {
4772 if Value != nil {
4773 Val, er := kvstore.ToByte(Value.Value)
4774 if er != nil {
4775 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4776 return signature
4777 }
4778 if er = json.Unmarshal(Val, &signature); er != nil {
4779 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4780 return signature
4781 }
4782 }
4783 }
4784 return signature
4785}
Akash Reddy Kankanala78b627f2026-01-12 08:18:21 +00004786
4787func (dh *DeviceHandler) UpdateDevice(ctx context.Context, updateDevice *voltha.UpdateDevice) {
4788 var dhCtx context.Context
4789 logger.Debug(ctx, "UpdateDevice called", log.Fields{"deviceConfig": updateDevice})
4790 dh.lockDevice.Lock()
4791 if dh.transitionHandlerCancel != nil {
4792 dh.transitionHandlerCancel() //if the previous device transition was grpc blocked on old IP,this make that handler return/exit.
4793 dh.transitionHandlerCancel = nil
4794 }
4795 err := updateDeviceAddress(dh.device, updateDevice) //update the device handler with the new device which would have newIP
4796 if err != nil {
4797 dh.lockDevice.Unlock()
4798 logger.Errorw(ctx, "failed-to-update-device-address", log.Fields{"error": err})
4799 return
4800 }
4801 connectStatus := dh.device.ConnectStatus
4802 dhCtx, dh.transitionHandlerCancel = context.WithCancel(context.Background())
4803 dh.lockDevice.Unlock()
4804 if connectStatus == voltha.ConnectStatus_REACHABLE {
4805 dh.updateStateUnreachable(dhCtx)
4806 } else {
4807 dh.transitionMap.Handle(dhCtx, DeviceInit)
4808 }
4809}
4810
4811func updateDeviceAddress(device *voltha.Device, deviceConfig *voltha.UpdateDevice) error {
4812 switch addr := deviceConfig.Address.(type) {
4813 case *voltha.UpdateDevice_Ipv4Address:
4814 if current, ok := device.Address.(*voltha.Device_Ipv4Address); ok {
4815 if current.Ipv4Address == addr.Ipv4Address {
4816 return fmt.Errorf("no-change-in-IPV4-device-address")
4817 }
4818 device.Address = &voltha.Device_Ipv4Address{Ipv4Address: addr.Ipv4Address}
4819 }
4820 case *voltha.UpdateDevice_Ipv6Address:
4821 if current, ok := device.Address.(*voltha.Device_Ipv6Address); ok {
4822 if current.Ipv6Address == addr.Ipv6Address {
4823 return fmt.Errorf("no-change-in-IPV6-device-address")
4824 }
4825 device.Address = &voltha.Device_Ipv6Address{Ipv6Address: addr.Ipv6Address}
4826 }
4827 case *voltha.UpdateDevice_HostAndPort:
4828 if current, ok := device.Address.(*voltha.Device_HostAndPort); ok {
4829 if current.HostAndPort == addr.HostAndPort {
4830 return fmt.Errorf("no-change-in-HostAndPort-device-address")
4831 }
4832 device.Address = &voltha.Device_HostAndPort{HostAndPort: addr.HostAndPort}
4833 }
4834 default:
4835 return fmt.Errorf("invalid-device-config-address-type")
4836 }
4837 return nil
4838}