blob: 7ef96399954ef4f57f8c0fadd5ff9c907d316c4c [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Phaneendra Manda4c62c802019-03-06 21:37:49 +05303
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Mahir Gunyela2e68702022-12-07 00:00:42 -080017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
Abhay Kumard3f18512025-12-09 07:51:12 +000042 grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
khenaidoo106c61a2021-08-11 18:05:46 -040043 "github.com/opencord/voltha-lib-go/v7/pkg/config"
44 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
45 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
46 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070047 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040048 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080049
nikesh.krishnand9812542023-08-01 18:31:39 +053050 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
khenaidoo106c61a2021-08-11 18:05:46 -040051 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053052 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080053 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040056 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040057 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
58 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040059 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
60 oop "github.com/opencord/voltha-protos/v5/go/openolt"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +053061 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
khenaidoo106c61a2021-08-11 18:05:46 -040062 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070063 "google.golang.org/grpc"
nikesh.krishnand9812542023-08-01 18:31:39 +053064 codes "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040065 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053066)
67
salmansiddiqui7ac62132019-08-22 03:58:50 +000068// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040069const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080070 InvalidPort = 0xffffffff
71 MaxNumOfGroupHandlerChannels = 256
72
73 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
74 McastFlowOrGroupModify = "McastFlowOrGroupModify"
75 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050076 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010077
78 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053079 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040080)
81
Mahir Gunyela2e68702022-12-07 00:00:42 -080082// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053083type DeviceHandler struct {
Akash Kankanala041a2122024-10-16 15:49:22 +053084 EventProxy eventif.EventProxy
85 Client oop.OpenoltClient
86 cm *config.ConfigManager
87 device *voltha.Device
88 cfg *conf.AdapterFlags
89 coreClient *vgrpc.Client
90 childAdapterClients map[string]*vgrpc.Client
91 openOLT *OpenOLT
92 exitChannel chan struct{}
93 transitionMap *TransitionMap
94 clientCon *grpc.ClientConn
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070098
99 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530100
Akash Kankanala041a2122024-10-16 15:49:22 +0530101 portStats *OpenOltStatisticsMgr
102 metrics *pmmetrics.PmMetrics
103 stopCollector chan bool
104 stopHeartbeatCheck chan bool
105 stopIndications chan bool
106 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
107
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700108 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
109 // if the value is true that means the OnuDiscovery indication
110 // is currently being processed and thus we can ignore concurrent requests
111 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
112 // if we do it means something went wrong and we need to retry
Akash Kankanala041a2122024-10-16 15:49:22 +0530113 discOnus sync.Map
114 onus sync.Map
115 activePorts sync.Map
116 flowMgr []*OpenOltFlowMgr
117 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra491a9c62021-01-06 16:43:07 -0800118
119 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
120 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700121 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
122 stopMcastHandlerRoutine []chan bool
123 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000124
Akash Kankanala041a2122024-10-16 15:49:22 +0530125 lockChildAdapterClients sync.RWMutex
126 lockDevice sync.RWMutex
127 perPonOnuIndicationChannelLock sync.Mutex
128
129 totalPonPorts uint32
130 heartbeatSignature uint32
131 isCollectorActive bool
132 isHeartbeatCheckActive bool
133 isReadIndicationRoutineActive bool
134
Gamze Abakac2c32a62021-03-11 11:44:18 +0000135 adapterPreviouslyConnected bool
136 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700137
138 isDeviceDeletionInProgress bool
Nandita Biradar1b590f12024-09-27 10:56:28 +0530139 prevOperStatus common.OperStatus_Types
bseenivaaa9165b2025-09-18 17:28:12 +0530140 collectorWaitGroup sync.WaitGroup
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700141}
142
Mahir Gunyela2e68702022-12-07 00:00:42 -0800143// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700144type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400145 deviceID string
146 deviceType string
147 serialNumber string
Akash Kankanala041a2122024-10-16 15:49:22 +0530148 proxyDeviceID string
149 adapterEndpoint string
khenaidoo106c61a2021-08-11 18:05:46 -0400150 onuID uint32
151 intfID uint32
khenaidoo106c61a2021-08-11 18:05:46 -0400152 losRaised bool
153 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700154}
155
Mahir Gunyelb0046752021-02-26 13:51:05 -0800156type onuIndicationMsg struct {
157 ctx context.Context
158 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800159}
160
161type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800162 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800163 stopChannel chan struct{}
164}
165
Mahir Gunyela2e68702022-12-07 00:00:42 -0800166// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
167// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
168// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
169// 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 -0800170type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400171 ctx context.Context // Flow/group handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400172 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
173 group *of.OfpGroupEntry // Group message (can be nil or valid group)
174 errChan *chan error // channel to report the mcast Flow/group handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530175 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
Girish Gowdra491a9c62021-01-06 16:43:07 -0800176}
177
Naga Manjunath7615e552019-10-11 22:35:47 +0530178var pmNames = []string{
179 "rx_bytes",
180 "rx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530181 "rx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530182 "rx_mcast_packets",
183 "rx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530184 "rx_error_packets",
185 "rx_crc_errors",
186 "rx_packets_dropped",
Naga Manjunath7615e552019-10-11 22:35:47 +0530187 "tx_bytes",
188 "tx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530189 "tx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530190 "tx_mcast_packets",
191 "tx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530192 "tx_error_packets",
193 "tx_dropped_total",
Naga Manjunath7615e552019-10-11 22:35:47 +0530194}
195
Mahir Gunyela2e68702022-12-07 00:00:42 -0800196// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400197func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700198 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700200 device.deviceType = deviceTp
201 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700202 device.onuID = onuID
203 device.intfID = intfID
204 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530205 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400206 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700207 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530208}
209
Mahir Gunyela2e68702022-12-07 00:00:42 -0800210// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400211func 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 -0700212 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530213 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800214 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400215 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400216 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700217 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 dh.device = cloned
219 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500220 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700221 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000222 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
223 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530224 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500225 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800226 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800227 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400228 dh.childAdapterClients = make(map[string]*vgrpc.Client)
229 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300230 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530231 if dh.kvStore == nil {
232 logger.Error(ctx, "Failed to setup KV store")
233 return nil
234 }
235
Girish Gowdra491a9c62021-01-06 16:43:07 -0800236 // Create a slice of buffered channels for handling concurrent mcast flow/group.
237 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700238 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
239 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800240 for i := range dh.incomingMcastFlowOrGroup {
241 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800242 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800243 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
244 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
245 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
246 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700247 dh.mcastHandlerRoutineActive[i] = true
248 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800249 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530250 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530252}
253
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530254func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
255 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
256 switch storeType {
257 case "etcd":
258 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530259 case "redis":
260 return kvstore.NewRedisClient(address, timeout, false)
261 case "redis-sentinel":
262 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530263 }
264 return nil, errors.New("unsupported-kv-store")
265}
266
267// SetKVClient sets the KV client and return a kv backend
268func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
269 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
270 if err != nil {
271 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
272 return nil
273 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530274 kvbackend := &db.Backend{
275 Client: kvClient,
276 StoreType: backend,
277 Address: addr,
278 Timeout: rsrcMgr.KvstoreTimeout,
279 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
280
281 return kvbackend
282}
283
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000284// CloseKVClient closes open KV clients
Abhay Kumarb87ac882025-10-30 09:55:07 +0000285// This method is thread-safe and can be called concurrently
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000286func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
Abhay Kumarb87ac882025-10-30 09:55:07 +0000287 // Acquire read lock to safely iterate over resourceMgr and flowMgr slices
288 // Use RLock since we're only reading the slices, not modifying them
289 dh.lockDevice.RLock()
290 defer dh.lockDevice.RUnlock()
291
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000292 if dh.resourceMgr != nil {
293 for _, rscMgr := range dh.resourceMgr {
294 if rscMgr != nil {
295 rscMgr.CloseKVClient(ctx)
296 }
297 }
298 }
299 if dh.flowMgr != nil {
300 for _, flMgr := range dh.flowMgr {
301 if flMgr != nil {
302 flMgr.CloseKVClient(ctx)
303 }
304 }
305 }
306}
307
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308// start save the device to the data model
309func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700310 dh.lockDevice.Lock()
311 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700313 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000314 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530315}
316
khenaidooefff76e2021-12-15 16:51:30 -0500317// Stop stops the device handler
318func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700319 dh.lockDevice.Lock()
320 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500322 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400323
khenaidooefff76e2021-12-15 16:51:30 -0500324 // Delete (which will stop also) all grpc connections to the child adapters
325 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000326 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530327}
328
ssiddiqui04386ee2021-08-23 21:58:25 +0530329func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
330 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
331 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
332 if pooledIntfID == intfID {
333 return resourceRanges.GetTechnology()
334 }
335 }
336 }
337 return ""
338}
339
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400340func macifyIP(ip net.IP) string {
341 if len(ip) > 0 {
342 oct1 := strconv.FormatInt(int64(ip[12]), 16)
343 oct2 := strconv.FormatInt(int64(ip[13]), 16)
344 oct3 := strconv.FormatInt(int64(ip[14]), 16)
345 oct4 := strconv.FormatInt(int64(ip[15]), 16)
346 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
347 }
348 return ""
349}
350
Neha Sharma96b7bf22020-06-15 10:37:32 +0000351func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400352 var genmac string
353 var addr net.IP
354 var ips []string
355 var err error
356
Neha Sharma96b7bf22020-06-15 10:37:32 +0000357 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400358
359 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000360 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400361
362 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000363 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400364 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000365 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400366 }
367 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000368 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530369 log.Fields{"host": ips[0],
370 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400371 return genmac, nil
372 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000373 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400374 }
375
376 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000377 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530378 log.Fields{"host": host,
379 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400380 return genmac, nil
381}
382
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530383func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700384 slist := strings.Split(mac, ":")
385 result := make([]uint32, len(slist))
386 var err error
387 var tmp int64
388 for index, val := range slist {
389 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
390 return []uint32{1, 2, 3, 4, 5, 6}
391 }
392 result[index] = uint32(tmp)
393 }
394 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530395}
396
Mahir Gunyela2e68702022-12-07 00:00:42 -0800397// 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 -0800398func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800399 switch portType {
400 case voltha.Port_ETHERNET_NNI:
401 return fmt.Sprintf("nni-%d", portNum), nil
402 case voltha.Port_PON_OLT:
403 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700404 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800405
Girish Kumarf26e4882020-03-05 06:49:10 +0000406 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530407}
408
Elia Battiston596406d2022-02-02 12:19:00 +0100409func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
410 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530411 // In case it was not set in the indication
412 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100413 speedMbps = defaultPortSpeedMbps
414 }
415
416 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
417 switch speedMbps {
418 case 1000000:
419 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
420 case 100000:
421 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
422 case 40000:
423 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
424 case 10000:
425 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
426 case 1000:
427 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
428 case 100:
429 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
430 case 10:
431 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
432 }
433
434 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
435
436 port := &of.OfpPort{
437 HwAddr: macAddressToUint32Array(macAddress),
438 Config: 0,
439 State: uint32(of.OfpPortState_OFPPS_LIVE),
440 Curr: capacity,
441 Advertised: capacity,
442 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530443 CurrSpeed: speedMbps * 1000, // kbps
444 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100445 }
446
447 return port
448}
449
450func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000451 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 if state == "up" {
453 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530454 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500455 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700456 } else {
457 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500458 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700459 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700460 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400461 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000463 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400464 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500465
khenaidoo106c61a2021-08-11 18:05:46 -0400466 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400467 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400468 DeviceId: dh.device.Id,
469 Port: portNum,
470 })
471 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000472 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400473 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400474 DeviceId: dh.device.Id,
475 PortType: portType,
476 PortNo: portNum,
477 OperStatus: operStatus})
478 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400479 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
480 "device-id": dh.device.Id,
481 "port-type": portType,
482 "port-number": portNum,
483 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500484 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400485 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500486 }
khenaidoo106c61a2021-08-11 18:05:46 -0400487
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400488 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400489 port = &voltha.Port{
490 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700491 PortNo: portNum,
492 Label: label,
493 Type: portType,
494 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100495 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700496 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700498 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400499 err = dh.createPortInCore(ctx, port)
500 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000501 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800502 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000503 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400504 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000505 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530506 return nil
507}
508
Kent Hagermane6ff1012020-07-14 15:07:53 -0400509func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400510 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530511 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400512 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
513 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530514 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800515 dh.lockDevice.Lock()
516 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530517 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530518}
519
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700520// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530521// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800522func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000523 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700524 defer func() {
525 dh.lockDevice.Lock()
526 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530527 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700528 dh.lockDevice.Unlock()
529 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700530 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700531 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700532 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700533 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400534
David Bainbridgef5879ca2019-12-13 21:17:54 +0000535 // Create an exponential backoff around re-enabling indications. The
536 // maximum elapsed time for the back off is set to 0 so that we will
537 // continue to retry. The max interval defaults to 1m, but is set
538 // here for code clarity
539 indicationBackoff := backoff.NewExponentialBackOff()
540 indicationBackoff.MaxElapsedTime = 0
541 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700542
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700543 dh.lockDevice.Lock()
544 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530545 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700546 dh.lockDevice.Unlock()
547
Girish Gowdra3f974912020-03-23 20:35:18 -0700548Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700549 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400550 select {
551 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000552 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700553 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400554 default:
555 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100556
557 select {
558 case <-indications.Context().Done():
559 if err != nil {
560 logger.Warnw(ctx, "error-during-enable-indications",
561 log.Fields{"err": err,
562 "device-id": dh.device.Id})
563 }
564
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400565 // Use an exponential back off to prevent getting into a tight loop
566 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100567 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
568 "device-id": dh.device.Id,
569 "duration": duration,
570 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400571 if duration == backoff.Stop {
572 // If we reach a maximum then warn and reset the backoff
573 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100574 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530575 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530576 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400577 indicationBackoff.Reset()
578 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700579
580 // On failure process a backoff timer while watching for stopIndications
581 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700582 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700583 select {
584 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000585 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700586 if !backoffTimer.Stop() {
587 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700588 }
589 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700590 case <-backoffTimer.C:
591 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700592 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700593 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
594 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400595 }
596 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100597 default:
598 if err != nil {
599 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530600 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530601 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100602 // Close the stream, and re-initialize it
603 if err = indications.CloseSend(); err != nil {
604 // Ok to ignore here, because we landed here due to a problem on the stream
605 // In all probability, the closeSend call may fail
606 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
607 log.Fields{"err": err,
608 "device-id": dh.device.Id})
609 }
610 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
611 return err
612 }
613 // once we re-initialized the indication stream, continue to read indications
614 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700615 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100616 // Reset backoff if we have a successful receive
617 indicationBackoff.Reset()
618 // When OLT is admin down, ignore all indications.
619 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
620 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
621 log.Fields{"indication": indication,
622 "device-id": dh.device.Id})
623 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700624 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100625 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530626 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700627 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700629 // Close the send stream
630 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700631
Girish Gowdra3f974912020-03-23 20:35:18 -0700632 return nil
633}
634
635func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700636 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700637 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
638 if err != nil {
639 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
640 }
641 if indications == nil {
642 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
643 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700644 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700645 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400646}
647
648// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
649func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
650 switch indication.Data.(type) {
651 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
652 return true
653
654 default:
655 return false
656 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657}
658
David K. Bainbridge794735f2020-02-11 21:01:37 -0800659func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700660 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000661 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530662 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700663 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530664 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000666 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000667 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530668 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000669 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800670 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000671 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800672 }
673 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674}
675
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530676func (dh *DeviceHandler) handleOnuDisableIndication(ctx context.Context, onuIndication *oop.OnuDisabledIndication) error {
677 logger.Infow(ctx, "handleOnuDisableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
678 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
679 intfID := onuIndication.GetIntfId()
680 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
681 onuDev := dh.getChildDevice(ctx, sn, ponPort)
682 if onuDev == nil {
683 logger.Warnw(ctx, "handleOnuDisableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
684 onuDev = &OnuDevice{
685 serialNumber: sn,
686 }
687 }
688 dh.discOnus.Delete(sn)
689
690 raisedTs := time.Now().Unix()
691 if err := dh.eventMgr.onuDisableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
692 return olterrors.NewErrAdapter("failed-indication", log.Fields{
693 "device-id": dh.device.Id,
694 "indication": onuIndication,
695 "timestamp": raisedTs}, err)
696 }
697 OnuIndication := generateOnuIndication(onuDev.intfID, onuDev.onuID, "down", "down")
698 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDev.adapterEndpoint, &ia.OnuIndicationMessage{
699 DeviceId: onuDev.deviceID,
700 OnuIndication: OnuIndication.GetOnuInd(),
701 })
702 if err != nil {
703 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
704 "onu-indicator": OnuIndication.GetOnuInd(),
705 "source": dh.openOLT.config.AdapterEndpoint,
706 "device-type": onuDev.deviceType,
707 "device-id": onuDev.deviceID}, err)
708 }
709 return nil
710}
711
712func (dh *DeviceHandler) handleOnuEnableIndication(ctx context.Context, onuIndication *oop.OnuEnabledIndication) error {
713 logger.Infow(ctx, "handleOnuEnableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
714 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
715 intfID := onuIndication.GetIntfId()
716 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
717 onuDev := dh.getChildDevice(ctx, sn, ponPort)
718 if onuDev == nil {
719 logger.Warnw(ctx, "handleOnuEnableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
720 onuDev = &OnuDevice{
721 serialNumber: sn,
722 }
723 }
724 raisedTs := time.Now().Unix()
725
726 if err := dh.eventMgr.onuEnableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
727 return olterrors.NewErrAdapter("failed-indication", log.Fields{
728 "device-id": dh.device.Id,
729 "indication": onuIndication,
730 "timestamp": raisedTs}, err)
731 }
732 return nil
733}
734
Akash Kankanala041a2122024-10-16 15:49:22 +0530735// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530736func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700737 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700738 switch indication.Data.(type) {
739 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000740 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
741 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700742 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 -0800743 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400744 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800745 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700746 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000747 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
748 defer span.Finish()
749
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700750 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800751 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100752 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400753 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800754 }
755 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000756 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700757 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000758 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
759 defer span.Finish()
760
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 intfOperInd := indication.GetIntfOperInd()
762 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800763 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100764 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400765 _ = 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 -0800766 }
767 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 } else if intfOperInd.GetType() == "pon" {
769 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
770 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800771 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100772 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400773 _ = 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 -0800774 }
775 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000776 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700777 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000778 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530779 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530780 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000782 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
783 defer span.Finish()
784
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700785 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000786 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530787 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800788 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700789 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000790 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
791 defer span.Finish()
792
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700793 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000794 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530795 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800796 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700797 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000798 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
799 defer span.Finish()
800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000802 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 -0800803 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000804 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400805 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800806 }
807 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700808 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000809 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
810 defer span.Finish()
811
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700812 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000813 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700814 "intf-type": pktInd.IntfId,
815 "intf-id": pktInd.IntfId,
816 "gem-port-id": pktInd.GemportId,
817 "port-no": pktInd.PortNo,
818 "device-id": dh.device.Id,
819 })
820
821 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000822 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700823 "intf-type": pktInd.IntfId,
824 "intf-id": pktInd.IntfId,
825 "gem-port-id": pktInd.GemportId,
826 "port-no": pktInd.PortNo,
827 "packet": hex.EncodeToString(pktInd.Pkt),
828 "device-id": dh.device.Id,
829 })
830 }
831
David K. Bainbridge794735f2020-02-11 21:01:37 -0800832 go func() {
833 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400834 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800835 }
836 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000838 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
839 defer span.Finish()
840
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700841 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700842 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700843 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000844 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
845 defer span.Finish()
846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000848 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700849 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000850 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
851 defer span.Finish()
852
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700853 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000854 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
855 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530856 case *oop.Indication_OnuDisabledInd:
857 span, ctx := log.CreateChildSpan(ctx, "onu-disable-indication", log.Fields{"device-id": dh.device.Id})
858 defer span.Finish()
859 logger.Infow(ctx, "received onu-disable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
860 if err := dh.handleOnuDisableIndication(ctx, indication.GetOnuDisabledInd()); err != nil {
861 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
862 }
863 case *oop.Indication_OnuEnabledInd:
864 span, ctx := log.CreateChildSpan(ctx, "onu-enable-indication", log.Fields{"device-id": dh.device.Id})
865 defer span.Finish()
866 logger.Infow(ctx, "received onu-enable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
867 if err := dh.handleOnuEnableIndication(ctx, indication.GetOnuEnabledInd()); err != nil {
868 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
869 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700870 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530871}
872
nikesh.krishnanc8473432023-06-14 12:14:54 +0530873func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
874 onuInd := &oop.OnuIndication{
875 IntfId: intfID,
876 OnuId: onuID,
877 OperState: operState,
878 AdminState: adminState,
879 }
880 indication := &oop.Indication{
881 Data: &oop.Indication_OnuInd{
882 OnuInd: onuInd,
883 },
884 }
885 return indication
886}
887
888func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
889 onuAlarmInd := &oop.OnuAlarmIndication{
890 IntfId: intfID,
891 OnuId: onuID,
892 LosStatus: losStatus,
893 }
894 alarmInd := &oop.AlarmIndication{
895 Data: &oop.AlarmIndication_OnuAlarmInd{
896 OnuAlarmInd: onuAlarmInd,
897 },
898 }
899 return alarmInd
900}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530901
Akash Kankanala041a2122024-10-16 15:49:22 +0530902func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530903 ponlosAlarmInd := &oop.LosIndication{
904 IntfId: intfID,
905 Status: losStatus,
906 }
907 alarmInd := &oop.AlarmIndication{
908 Data: &oop.AlarmIndication_LosInd{
909 LosInd: ponlosAlarmInd,
910 },
911 }
912 return alarmInd
913}
Akash Kankanala041a2122024-10-16 15:49:22 +0530914
nikesh.krishnanc8473432023-06-14 12:14:54 +0530915func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
916 go func() {
917 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
918 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
919 }
920 }()
921
922 raisedTs := time.Now().Unix()
923 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
924}
925
926func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530927 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
928 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530929 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530930 return err
931 }
932 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530933 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
934 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
935 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
936
937 onuID := onuDeviceFromCore.ProxyAddress.OnuId
938 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
939 if err != nil {
940 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530941 } else {
942 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
943 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
944 switch {
945 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
946 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
947 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
948
949 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530950 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530951 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
952 raisedTs := time.Now().Unix()
953 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
954
955 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
956 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530957 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530958 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530959 return nil
960}
961
962func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
963 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
964 DeviceId: dh.device.Id,
965 PortType: voltha.Port_PON_OLT,
966 })
967 if err != nil {
968 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530969 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530970 }
971 for _, portFromCore := range portsFromCore.Items {
972 portNum := portFromCore.GetPortNo()
973 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
974 portOperStatusFromCore := portFromCore.OperStatus
975 portAdminStateFromCore := portFromCore.AdminState
976 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
977 if err != nil {
978 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
979 } else {
980 portLosFromOlt := ponPortFromOlt.GetLos()
981 portStateFromOlt := ponPortFromOlt.GetState()
982 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
983 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
984 "portStateFromOlt": portStateFromOlt.String(),
985 "portOperStatusFromCore": portOperStatusFromCore.String(),
986 "device-id": dh.device.Id,
987 "port": portNum})
988 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
989 raisedTs := time.Now().Unix()
990 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530991 }
992 switch {
993 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
994 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
995 "portStateFromOlt": portStateFromOlt.String(),
996 "portOperStatusFromCore": portOperStatusFromCore.String(),
997 "device-id": dh.device.Id,
998 "port": portNum})
999 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
1000 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
1001 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
1002 "portStateFromOlt": portStateFromOlt.String(),
1003 "portOperStatusFromCore": portOperStatusFromCore.String(),
1004 "device-id": dh.device.Id,
1005 "port": portNum})
1006 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
1007 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
1008 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
1009 "device-id": dh.device.Id,
1010 "port": portNum})
1011 default:
1012 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
1013 "portStateFromOlt": portStateFromOlt.String(),
1014 "portOperStatusFromCore": portOperStatusFromCore.String(),
1015 "device-id": dh.device.Id,
1016 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301017 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301018 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301019 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301020 return nil
1021}
1022
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301023// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301024func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +05301025 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +05301026 // Declare deviceStateFilter to be used later
1027 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +05301028 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001029 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +05301030 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301031 if err != nil {
1032 return fmt.Errorf("failed to get device from core: %w", err)
1033 }
1034 logger.Info(ctx, "Device state", log.Fields{
1035 "device-id": device.Id,
1036 "CurrOperStatus": device.OperStatus,
1037 "CurrConnStatus": device.ConnectStatus,
1038 })
1039 // Perform cleanup if the device's operational status is REBOOTED
1040 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
1041 // Log the device's operational status if it's REBOOTED
1042 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
1043 "device-id": device.Id,
1044 "OperStatus": device.OperStatus,
1045 })
1046 dh.lockDevice.RLock()
1047 // Stop the read indication only if it the routine is active
1048 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1049 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1050 // on next execution of the readIndication routine.
1051 if dh.isHeartbeatCheckActive {
1052 dh.stopHeartbeatCheck <- true
1053 }
1054 if dh.isReadIndicationRoutineActive {
1055 dh.stopIndications <- true
1056 }
bseenivaaa9165b2025-09-18 17:28:12 +05301057 if dh.isCollectorActive {
1058 dh.stopCollector <- true
1059 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301060 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +05301061 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301062 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
1063 return fmt.Errorf("cleanup device resources failed: %w", err)
1064 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301065 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301066 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1067 }
bseenivaaa9165b2025-09-18 17:28:12 +05301068 dh.collectorWaitGroup.Add(1)
1069 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301070 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301071 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +05301072 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
1073 // Log the device's operational status if it's RECONCILING
1074 logger.Info(ctx, "Device is being reconciled", log.Fields{
1075 "device-id": device.Id,
1076 "OperStatus": device.OperStatus,
1077 })
1078
1079 // Perform reconciliation steps
1080 err = dh.reconcileOnus(ctx)
1081 if err != nil {
1082 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1083 }
1084 err = dh.reconcilePonPorts(ctx)
1085 if err != nil {
1086 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301087 }
1088 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001089 // instantiate the mcast handler routines.
1090 for i := range dh.incomingMcastFlowOrGroup {
1091 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1092 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1093 if !dh.mcastHandlerRoutineActive[i] {
1094 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1095 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1096 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1097 // for incoming mcast flow/group to be processed serially.
1098 dh.mcastHandlerRoutineActive[i] = true
1099 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1100 }
1101 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301102 // Create DeviceStateFilter with the desired operational and connection statuses
1103 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001104 DeviceId: dh.device.Id,
1105 OperStatus: voltha.OperStatus_ACTIVE,
1106 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301107 }
1108 // Log DeviceStateFilter for debugging purposes
1109 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1110 "DeviceId": deviceStateFilter.DeviceId,
1111 "OperStatus": deviceStateFilter.OperStatus,
1112 "ConnStatus": deviceStateFilter.ConnStatus,
1113 })
1114 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301115 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001116 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001117 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001118
Akash Kankanala041a2122024-10-16 15:49:22 +05301119 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001120 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1121 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301122
1123 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1124 if err != nil {
1125 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1126 }
1127 dh.populateActivePorts(ctx, ports.Items)
1128 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1129 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1130 }
1131
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001132 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001133 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1134
Girish Gowdru0c588b22019-04-23 23:24:56 -04001135 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301136}
1137
1138// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301139func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001140 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001141
khenaidoo106c61a2021-08-11 18:05:46 -04001142 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001143 if err != nil || device == nil {
1144 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001145 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001146 }
1147
1148 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001149
Akash Kankanala041a2122024-10-16 15:49:22 +05301150 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001151 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001152 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001153 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001154 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001155
khenaidoodc2116e2021-10-19 17:33:19 -04001156 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001157 DeviceId: cloned.Id,
1158 OperStatus: cloned.OperStatus,
1159 ConnStatus: cloned.ConnectStatus,
1160 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001161 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001162 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001163
Akash Kankanala041a2122024-10-16 15:49:22 +05301164 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001165 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001166 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001167 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001168 }
1169 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001170 // Update onu state as down in onu adapter
1171 onuInd := oop.OnuIndication{}
1172 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001173
1174 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1175 if err != nil {
1176 return err
1177 }
1178 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001179 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001180 DeviceId: onuDevice.Id,
1181 OnuIndication: &onuInd,
1182 })
1183 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001184 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001185 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001186 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 "onu-indicator": onuInd,
1188 "device-type": onuDevice.Type,
1189 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301190 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001191 } else {
1192 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 -07001193 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001194 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001195 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001196 /* Discovered ONUs entries need to be cleared , since after OLT
1197 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301198 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001199 dh.lockDevice.Unlock()
1200
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001202 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301203}
1204
1205// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301206func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001207 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001208
1209 // if the connection is already available, close the previous connection (olt reboot case)
1210 if dh.clientCon != nil {
1211 if err = dh.clientCon.Close(); err != nil {
1212 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1213 } else {
1214 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1215 }
1216 }
1217
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301218 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Abhay Kumard3f18512025-12-09 07:51:12 +00001219 grpc_prometheus.EnableClientHandlingTimeHistogram()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001220 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001221 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1222 grpc.WithInsecure(),
1223 grpc.WithBlock(),
1224 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001225 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001226 grpc_prometheus.StreamClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001227 )),
1228 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001229 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001230 grpc_prometheus.UnaryClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001231 )))
1232
1233 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301234 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301235 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001236 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001237 }
Akash Sonif49299a2024-04-25 12:06:37 +05301238 //Setting oper and connection state to RECONCILING and conn state to reachable
1239 cgClient, err := dh.coreClient.GetCoreServiceClient()
1240 if err != nil {
1241 return err
1242 }
1243
1244 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1245 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1246 defer cancel()
1247 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1248 DeviceId: dh.device.Id,
1249 OperStatus: voltha.OperStatus_RECONCILING,
1250 ConnStatus: voltha.ConnectStatus_REACHABLE,
1251 }); err != nil {
1252 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1253 }
1254 // 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
1255 // locally cached copy of the device struct.
1256 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1257 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1258 }
1259
Girish Gowdru0c588b22019-04-23 23:24:56 -04001260 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301261}
1262
1263// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301264func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001265 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301266 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001267 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301268}
1269
1270// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301271func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301272 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001273 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001274
1275 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001276 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301277 if err != nil || device == nil {
1278 /*TODO: needs to handle error scenarios */
1279 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1280 }
1281 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001282 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001283
1284 cloned := proto.Clone(device).(*voltha.Device)
1285 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1286 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1287 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001288
khenaidoodc2116e2021-10-19 17:33:19 -04001289 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001290 DeviceId: cloned.Id,
1291 OperStatus: cloned.OperStatus,
1292 ConnStatus: cloned.ConnectStatus,
1293 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301294 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 -04001295 }
1296
bseenivaa1622112025-12-11 18:24:02 +05301297 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Chaitrashree G S44124192019-08-07 20:21:36 -04001298 // 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 +05301299 _, err = dh.Client.DisableOlt(subCtx, new(oop.Empty))
1300 cancel()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001301 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301302 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001303 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001304 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1305 // all the modules initialized and ready to handle incoming ONUs.
1306
Thomas Lee S985938d2020-05-04 11:40:41 +05301307 err = dh.initializeDeviceHandlerModules(ctx)
1308 if err != nil {
1309 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 -04001310 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001311
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001312 go startHeartbeatCheck(ctx, dh)
1313
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001314 return nil
1315 }
1316
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001317 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301318 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001319 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301320
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001322
1323 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001325 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001326
1327 go startHeartbeatCheck(ctx, dh)
1328
cuilin20187b2a8c32019-03-26 19:52:28 -07001329 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301330}
1331
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001332func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001333 var err error
1334 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001335
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001336 if dh.flowMgr != nil {
1337 dh.StopAllFlowRoutines(ctx)
1338 }
1339
1340 dh.CloseKVClient(ctx)
1341
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001342 if err != nil {
1343 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1344 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001345 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1346 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301347 // If collector go routine is active, wait for it to stop
1348 dh.lockDevice.RLock()
1349 if dh.isCollectorActive {
1350 dh.lockDevice.RUnlock()
1351 dh.collectorWaitGroup.Wait()
1352 } else {
1353 dh.lockDevice.RUnlock()
1354 }
yasin saplid0566272021-12-21 09:10:30 +00001355 // +1 is for NNI
1356 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1357 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001358 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001359 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1360 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1361 // There is only one NNI manager since multiple NNI is not supported for now
1362 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001363 // Instantiate resource manager
1364 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 -07001365 return olterrors.ErrResourceManagerInstantiating
1366 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001367 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001368 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1369 // the KV store to manage mcast group data. Provide the first instance (0th index)
1370 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1371 return olterrors.ErrGroupManagerInstantiating
1372 }
yasin saplid0566272021-12-21 09:10:30 +00001373 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001374 // Instantiate flow manager
1375 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301376 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001377 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1378 } else {
1379 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001380 }
1381 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001382 /* TODO: Instantiate Alarm , stats , BW managers */
1383 /* Instantiating Event Manager to handle Alarms and KPIs */
1384 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1385
1386 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001388
1389 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001390}
1391
Neha Sharma96b7bf22020-06-15 10:37:32 +00001392func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001393 var err error
1394 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301395 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001396
bseenivaa1622112025-12-11 18:24:02 +05301397 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1398 deviceInfo, err = dh.Client.GetDeviceInfo(subCtx, new(oop.Empty))
1399 cancel()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001400
1401 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001402 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001403 }
1404 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001405 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001406 }
1407
Neha Sharma96b7bf22020-06-15 10:37:32 +00001408 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001409 dh.device.Root = true
1410 dh.device.Vendor = deviceInfo.Vendor
1411 dh.device.Model = deviceInfo.Model
1412 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1413 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1414 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1415
1416 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001417 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001418 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301419 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001420 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001422 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001423 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001424 dh.device.MacAddress = genmac
1425 } else {
1426 dh.device.MacAddress = deviceInfo.DeviceId
1427 }
1428
1429 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001430 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001431 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001432 }
1433
1434 return deviceInfo, nil
1435}
1436
Neha Sharma96b7bf22020-06-15 10:37:32 +00001437func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301438 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001439
1440 defer func() {
1441 dh.lockDevice.Lock()
1442 dh.isCollectorActive = false
1443 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301444 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001445 }()
1446
1447 dh.lockDevice.Lock()
1448 dh.isCollectorActive = true
1449 dh.lockDevice.Unlock()
1450
Naga Manjunath7615e552019-10-11 22:35:47 +05301451 for {
1452 select {
1453 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301454 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301455 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001456 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001457
khenaidoo106c61a2021-08-11 18:05:46 -04001458 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001459 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001460 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001461 continue
1462 }
khenaidoo106c61a2021-08-11 18:05:46 -04001463 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301464 // NNI Stats
1465 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001466 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301467 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001468 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001469 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001470 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301471 }
1472 // PON Stats
1473 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001474 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301475 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1476 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001477 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001478 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301479 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001480 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001481
yasin sapli9e4c5092022-02-01 13:52:33 +00001482 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001483 if len(onuGemInfoLst) > 0 {
1484 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001485 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001486 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301487 }
1488 }
1489 }
1490}
1491
Mahir Gunyela2e68702022-12-07 00:00:42 -08001492// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301493func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001494 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001495 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301496 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301497
1498 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001499 cgClient, err := dh.coreClient.GetCoreServiceClient()
1500 if err != nil {
1501 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1502 return
1503 }
1504
1505 // Now, set the initial PM configuration for that device
1506 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001507 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301508 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301509}
1510
Mahir Gunyela2e68702022-12-07 00:00:42 -08001511// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001512func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1513 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001514 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301515 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001516 HwDesc: "open_pon",
1517 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001518 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001519 },
1520 SwitchFeatures: &of.OfpSwitchFeatures{
1521 NBuffers: 256,
1522 NTables: 2,
1523 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1524 of.OfpCapabilities_OFPC_TABLE_STATS |
1525 of.OfpCapabilities_OFPC_PORT_STATS |
1526 of.OfpCapabilities_OFPC_GROUP_STATS),
1527 },
1528 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301529}
1530
khenaidoo106c61a2021-08-11 18:05:46 -04001531// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001532func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001533 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001534 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001535 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001536 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001537 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1538 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()
1539 }
khenaidoo106c61a2021-08-11 18:05:46 -04001540 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001541}
1542
Neha Sharma96b7bf22020-06-15 10:37:32 +00001543func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001544 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 -07001545 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001546 var deviceID string
1547 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001548 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001549
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001550 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001551 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001552 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 -07001553 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1554 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001555
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001556 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301557
1558 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001559 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 -07001560 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001561
khenaidoodc2116e2021-10-19 17:33:19 -04001562 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001563 ParentId: dh.device.Id,
1564 OnuId: omciInd.OnuId,
1565 ParentPortNo: ponPort,
1566 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001567 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301568 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001569 "intf-id": omciInd.IntfId,
1570 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001571 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001572 deviceType = onuDevice.Type
1573 deviceID = onuDevice.Id
1574 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001575 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301576 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001577 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001578 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301579 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001580 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 +05301581 deviceType = onuInCache.(*OnuDevice).deviceType
1582 deviceID = onuInCache.(*OnuDevice).deviceID
1583 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001584 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001585 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001586
khenaidoodc2116e2021-10-19 17:33:19 -04001587 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001588 ParentDeviceId: proxyDeviceID,
1589 ChildDeviceId: deviceID,
1590 Message: omciInd.Pkt,
1591 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301592 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001593 "source": dh.openOLT.config.AdapterEndpoint,
1594 "device-type": deviceType,
1595 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001597 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001598 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001599 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301600}
1601
khenaidoo106c61a2021-08-11 18:05:46 -04001602// //ProcessInterAdapterMessage sends the proxied messages to the target device
1603// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1604// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001605// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001606// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001607// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001608// return dh.handleInterAdapterOmciMsg(ctx, msg)
1609// }
1610// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1611// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001612
kesavandb9f54fd2021-11-25 20:08:04 +05301613// ProxyOmciRequests sends the proxied OMCI message to the target device
1614func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301615 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1616 return status.Error(codes.Unavailable, "OLT unreachable")
1617 }
kesavandb9f54fd2021-11-25 20:08:04 +05301618 if omciMsgs.GetProxyAddress() == nil {
1619 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1620 if err != nil {
1621 return olterrors.NewErrNotFound("onu", log.Fields{
1622 "parent-device-id": dh.device.Id,
1623 "child-device-id": omciMsgs.ChildDeviceId}, err)
1624 }
1625 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1626 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1627 return olterrors.NewErrCommunication("send-failed", log.Fields{
1628 "parent-device-id": dh.device.Id,
1629 "child-device-id": omciMsgs.ChildDeviceId}, err)
1630 }
1631 } else {
1632 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1633 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1634 return olterrors.NewErrCommunication("send-failed", log.Fields{
1635 "parent-device-id": dh.device.Id,
1636 "child-device-id": omciMsgs.ChildDeviceId}, err)
1637 }
1638 }
1639 return nil
1640}
1641
1642func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1643 var intfID uint32
1644 var onuID uint32
1645 var connectStatus common.ConnectStatus_Types
1646 if onuDevice != nil {
1647 intfID = onuDevice.ProxyAddress.GetChannelId()
1648 onuID = onuDevice.ProxyAddress.GetOnuId()
1649 connectStatus = onuDevice.ConnectStatus
1650 } else {
1651 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1652 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1653 connectStatus = omciMsgs.GetConnectStatus()
1654 }
1655 if connectStatus != voltha.ConnectStatus_REACHABLE {
1656 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1657
1658 return olterrors.NewErrCommunication("unreachable", log.Fields{
1659 "intf-id": intfID,
1660 "onu-id": onuID}, nil)
1661 }
1662
1663 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1664 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1665
1666 onuSecOmciMsgList := omciMsgs.GetMessages()
1667
1668 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301669 var omciMessage *oop.OmciMsg
1670 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1671 hex.Encode(hexPkt, onuSecOmciMsg)
1672 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1673
1674 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1675 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1676 //https://jira.opencord.org/browse/VOL-4604
1677 transid := extractOmciTransactionID(onuSecOmciMsg)
1678 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1679 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1680
bseenivaa1622112025-12-11 18:24:02 +05301681 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1682 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1683 cancel()
kesavandb9f54fd2021-11-25 20:08:04 +05301684 if err != nil {
1685 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1686 "intf-id": intfID,
1687 "onu-id": onuID,
1688 "message": omciMessage}, err)
1689 }
1690 }
1691 return nil
1692}
1693
khenaidoo106c61a2021-08-11 18:05:46 -04001694// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001695func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001696 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 -07001697
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301698 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1699 return status.Error(codes.Unavailable, "OLT unreachable")
1700 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001701 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001702 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001703 if err != nil {
1704 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001705 "parent-device-id": dh.device.Id,
1706 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001707 }
khenaidoo106c61a2021-08-11 18:05:46 -04001708 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1709 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001710 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001711 "parent-device-id": dh.device.Id,
1712 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001713 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001714 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001715 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1716 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001717 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001718 "parent-device-id": dh.device.Id,
1719 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001720 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001721 }
1722 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301723}
1724
khenaidoodc2116e2021-10-19 17:33:19 -04001725func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001726 var intfID uint32
1727 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001728 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001729 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001730 intfID = onuDevice.ProxyAddress.GetChannelId()
1731 onuID = onuDevice.ProxyAddress.GetOnuId()
1732 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001733 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001734 intfID = omciMsg.GetProxyAddress().GetChannelId()
1735 onuID = omciMsg.GetProxyAddress().GetOnuId()
1736 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001737 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001738 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 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 -08001740
Thomas Lee S94109f12020-03-03 16:39:29 +05301741 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001742 "intf-id": intfID,
1743 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001744 }
1745
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001746 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1747 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301748 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001749 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001750 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1751 hex.Encode(hexPkt, omciMsg.Message)
1752 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1753
1754 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1755 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1756 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001757 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001758 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001759
bseenivaa1622112025-12-11 18:24:02 +05301760 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1761 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1762 cancel()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001763 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301764 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001765 "intf-id": intfID,
1766 "onu-id": onuID,
1767 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001768 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001769 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001770}
1771
David K. Bainbridge794735f2020-02-11 21:01:37 -08001772func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301773 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 +00001774 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001775 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001776 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001777 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301778 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
bseenivaa1622112025-12-11 18:24:02 +05301779 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1780 defer cancel()
1781 if _, err := dh.Client.ActivateOnu(subCtx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001782 st, _ := status.FromError(err)
1783 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001784 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 -04001785 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301786 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001787 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001788 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001789 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001790 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001791 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001792}
1793
Mahir Gunyela2e68702022-12-07 00:00:42 -08001794// getChildDevice function can be used in general to get child device, if not found in cache the function will
1795// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301796func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1797 var InCacheOnuDev *OnuDevice
1798 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1799 if onuInCache.(*OnuDevice).serialNumber == sn {
1800 InCacheOnuDev = onuInCache.(*OnuDevice)
1801 return false
1802 }
1803 return true
1804 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301805 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301806 if InCacheOnuDev != nil {
1807 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1808 return InCacheOnuDev
1809 }
1810 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1811 ParentId: dh.device.Id,
1812 SerialNumber: sn,
1813 ParentPortNo: parentPortNo,
1814 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301815 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301816 if onuDevice == nil {
1817 return nil
1818 }
1819 onuID := onuDevice.ProxyAddress.OnuId
1820 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1821 onuKey := dh.formOnuKey(intfID, onuID)
1822
1823 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1824 dh.onus.Store(onuKey, onuDev)
1825 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1826 return onuDev
1827}
1828
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301829// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1830// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301831func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001832 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301833 // 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 +05301834 // 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 +05301835 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1836 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1837 ParentId: dh.device.Id,
1838 SerialNumber: sn,
1839 ParentPortNo: parentPortNo,
1840 })
1841 if onuDevice != nil {
1842 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1843 return true, nil
1844 }
1845 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1846
1847 return false, nil
1848 } else {
1849 tpInstExists := false
1850 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301851 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1852 if onuDev != nil {
1853 var onuGemInfo *rsrcMgr.OnuGemInfo
1854 var err error
1855 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1856 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1857 return false, err
1858 }
1859 if onuGemInfo != nil {
1860 for _, uni := range onuGemInfo.UniPorts {
1861 uniID := plt.UniIDFromPortNum(uni)
1862 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1863 if len(tpIDs) != 0 {
1864 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1865 tpInstExists = true
1866 break
1867 }
1868 }
1869 }
1870 }
1871 return tpInstExists, nil
1872 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301873}
1874
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001875// processDiscONULOSClear clears the LOS Alarm if it's needed
1876func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301877 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001878 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301879
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001880 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1881 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1882 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1883 OnuLosRaise event sent for it */
1884 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1885 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1886 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1887 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1888 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1889 "currentIntfId": onuDiscInd.GetIntfId()})
1890 // TODO:: Should we need to ignore raising OnuLosClear event
1891 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301892 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001893 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1894 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1895 alarmInd.LosStatus = statusCheckOff
1896 go func() {
1897 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1898 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1899 }
1900 }()
1901 // stop iterating
1902 return false
1903 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301904 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001905 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301906}
1907
bseeniva43b5a912025-06-05 12:48:15 +05301908func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1909 if err != nil || tpInstExists {
1910 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1911 } else {
1912 // once the function completes set the value to false so that
1913 // we know the processing has inProcess.
1914 // Note that this is done after checking if we are already processing
1915 // to avoid changing the value from a different thread
1916 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1917 dh.discOnus.Store(sn, false)
1918 }
1919}
1920
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301921func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301922 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301923 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301924
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301925 channelID := onuDiscInd.GetIntfId()
1926 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1927
1928 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301929 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301930 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301931 }()
1932
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301933 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1934
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301935 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1936 if !dh.cfg.ForceOnuDiscIndProcessing {
1937 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1938 if error != nil {
1939 return error
1940 }
1941 if tpInstExists {
1942 // ignore the discovery if tpinstance is present.
1943 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1944 return nil
1945 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001946 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001947 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1948
1949 // if the ONU existed, handle the LOS Alarm
1950 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001951 if inProcess.(bool) {
1952 // if we're currently processing the ONU on a different thread, do nothing
1953 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1954 return nil
1955 }
1956 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1957 // then continue processing it
1958 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1959
1960 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001961 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301962 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001963 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001964
1965 // check the ONU is already know to the OLT
1966 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301967 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001968 ParentId: dh.device.Id,
1969 SerialNumber: sn,
1970 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001971
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301972 if error != nil {
1973 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1974 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 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 -08001976 switch e.Code() {
1977 case codes.Internal:
1978 // this probably means NOT FOUND, so just create a new device
1979 onuDevice = nil
1980 case codes.DeadlineExceeded:
1981 // if the call times out, cleanup and exit
1982 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301983 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1984 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001985 }
1986 }
1987 }
1988
1989 if onuDevice == nil {
1990 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001991 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001992 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001993 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301994 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001995 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001996
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301997 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001998 // if we can't create an ID in resource manager,
1999 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08002000 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302001
2002 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002003 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302004 "serial-number": sn}, error)
2005 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002006 }
2007
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302008 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04002009 ParentId: dh.device.Id,
2010 ParentPortNo: parentPortNo,
2011 ChannelId: channelID,
2012 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
2013 SerialNumber: sn,
2014 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302015 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002016 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00002017 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 +05302018
2019 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002020 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302021 "serial-number": sn}, error)
2022 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002023 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302024 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 +05302025 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2026 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2027 "onu-id": onuID,
2028 "device-id": dh.device.Id,
2029 "serial-number": sn}, error)
2030 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002031 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002032 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302033 log.Fields{"onuDevice": onuDevice,
2034 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002035 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302036 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002037 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002038
khenaidoo106c61a2021-08-11 18:05:46 -04002039 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2040 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302041 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002042 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302043 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302044 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2045 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002046 }
2047
Matteo Scandolo945e4012019-12-12 14:16:11 -08002048 // we can now use the existing ONU Id
2049 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302050 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002051 //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 +00002052 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002053 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302054 "intfId": onuDiscInd.GetIntfId(),
2055 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002056 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002057
khenaidoo106c61a2021-08-11 18:05:46 -04002058 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302059 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302061 log.Fields{"onu": onuDev,
2062 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002063
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302064 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002065 DeviceId: onuDevice.Id,
2066 ParentDeviceId: dh.device.Id,
2067 OperStatus: common.OperStatus_DISCOVERED,
2068 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302069 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302070 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002071 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302072 "serial-number": sn}, error)
2073 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002074 }
khenaidoo106c61a2021-08-11 18:05:46 -04002075
Neha Sharma96b7bf22020-06-15 10:37:32 +00002076 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302077 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302078 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002079 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302080 "serial-number": sn}, error)
2081 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002082 }
2083 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002084}
2085
Mahir Gunyelb0046752021-02-26 13:51:05 -08002086func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002087 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002088 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002089 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002090 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002091 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302092 log.Fields{"onuId": onuInd.OnuId,
2093 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302094 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002095 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002096 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002097 errFields := log.Fields{"device-id": dh.device.Id}
2098
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302099 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302100 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002101 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002102 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002103 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002104 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302105 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002106 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002107 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002108 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002109 errFields["onu-id"] = onuInd.OnuId
2110 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002111 }
khenaidoodc2116e2021-10-19 17:33:19 -04002112 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002113 ParentId: dh.device.Id,
2114 SerialNumber: serialNumber,
2115 OnuId: onuInd.OnuId,
2116 ParentPortNo: ponPort,
2117 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002118 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002119
David K. Bainbridge794735f2020-02-11 21:01:37 -08002120 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002121 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002122 }
2123
David K. Bainbridge794735f2020-02-11 21:01:37 -08002124 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002126 "previousIntfId": onuDevice.ParentPortNo,
2127 "currentIntfId": ponPort})
2128 }
2129
2130 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302132 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2133 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302134 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002135 }
2136 if !foundInCache {
2137 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002138 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 -08002139 }
kesavand7cf3a052020-08-28 12:49:18 +05302140 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002141 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002142 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302143 }
2144 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002146 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002147 }
2148 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002149}
2150
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152 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 -07002153 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2154 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2155 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2156 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002157 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002158 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2159 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002160 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002161 onuInd.OperState = "down"
2162 }
2163 }
2164
David K. Bainbridge794735f2020-02-11 21:01:37 -08002165 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002166 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002167 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 -04002168
khenaidoodc2116e2021-10-19 17:33:19 -04002169 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002170 DeviceId: onuDevice.Id,
2171 OnuIndication: onuInd,
2172 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002173 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302174 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002175 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002176 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002177 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002178 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002179 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002180 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002181 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002182 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002183 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002184}
2185
cuilin20187b2a8c32019-03-26 19:52:28 -07002186func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2187 if serialNum != nil {
2188 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002189 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002190 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002191}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002192func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2193 decodedStr, err := hex.DecodeString(serialNum[4:])
2194 if err != nil {
2195 return nil, err
2196 }
2197 return &oop.SerialNumber{
2198 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002199 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002200 }, nil
2201}
cuilin20187b2a8c32019-03-26 19:52:28 -07002202
2203func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002204 if len(vendorSpecific) > 3 {
2205 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2206 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2207 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2208 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2209 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2210 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2211 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2212 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2213 return tmp
2214 }
2215 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002216}
2217
Mahir Gunyela2e68702022-12-07 00:00:42 -08002218// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002219func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302220 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002221}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002222
Mahir Gunyela2e68702022-12-07 00:00:42 -08002223// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002224func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2225 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302226 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002227 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302228 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002229
khenaidoodc2116e2021-10-19 17:33:19 -04002230 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002231 ParentId: dh.device.Id,
2232 OnuId: onuID,
2233 ParentPortNo: parentPort,
2234 })
2235
Girish Gowdru0c588b22019-04-23 23:24:56 -04002236 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002237 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002238 "intf-id": parentPort,
2239 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002240 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002241 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 -08002242 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302243}
2244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002245// SendPacketInToCore sends packet-in to core
2246// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2247// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002248func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002249 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002250 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002251 "port": logicalPort,
2252 "packet": hex.EncodeToString(packetPayload),
2253 "device-id": dh.device.Id,
2254 })
2255 }
khenaidoo106c61a2021-08-11 18:05:46 -04002256
khenaidoodc2116e2021-10-19 17:33:19 -04002257 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002258 DeviceId: dh.device.Id,
2259 Port: logicalPort,
2260 Packet: packetPayload,
2261 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302262 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002263 "source": "adapter",
2264 "destination": "core",
2265 "device-id": dh.device.Id,
2266 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002267 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002268 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002269 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002270 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002271 "packet": hex.EncodeToString(packetPayload),
2272 "device-id": dh.device.Id,
2273 })
2274 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002275 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002276}
2277
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002278// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002281
2282 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2283 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002284 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002285 }
2286
Kent Hagermane6ff1012020-07-14 15:07:53 -04002287 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002288 metrics := dh.metrics.GetSubscriberMetrics()
2289 for _, m := range pmConfigs.Metrics {
2290 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002291 }
2292 }
2293}
2294
khenaidoodc2116e2021-10-19 17:33:19 -04002295func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002296 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002297 var errorsList []error
2298
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002299 if dh.getDeviceDeletionInProgressFlag() {
2300 // The device itself is going to be reset as part of deletion. So nothing to be done.
2301 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2302 return nil
2303 }
2304
Girish Gowdru0c588b22019-04-23 23:24:56 -04002305 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002306 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302307 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002308
Neha Sharma96b7bf22020-06-15 10:37:32 +00002309 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302310 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002311 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302312 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002313 if flow_utils.HasGroup(flow) {
2314 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2315 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002316 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2317 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2318 } else {
2319 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2320 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002321 }
Girish Gowdracefae192020-03-19 18:14:10 -07002322 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002323 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302324 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002325 logger.Warnw(ctx, "flow-to-remove-not-found",
2326 log.Fields{
2327 "ponIf": intfID,
2328 "flowToRemove": flow,
2329 "error": err,
2330 })
2331 } else {
2332 errorsList = append(errorsList, err)
2333 }
Girish Gowdracefae192020-03-19 18:14:10 -07002334 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002335 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302336
2337 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302338 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302340 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002341 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302342 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002343 if flow_utils.HasGroup(flow) {
2344 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2345 } else {
yasin saplid0566272021-12-21 09:10:30 +00002346 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002347 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2348 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2349 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2350 } else {
yasin saplid0566272021-12-21 09:10:30 +00002351 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002352 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002353 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002354 if err != nil {
2355 errorsList = append(errorsList, err)
2356 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302357 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002358 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002359
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002360 return errorsList
2361}
2362
2363func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2364 var err error
2365 var errorsList []error
2366
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002367 if dh.getDeviceDeletionInProgressFlag() {
2368 // The device itself is going to be reset as part of deletion. So nothing to be done.
2369 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2370 return nil
2371 }
2372
Girish Gowdracefae192020-03-19 18:14:10 -07002373 // 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 +00002374 if groups != nil {
2375 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002376 // err = dh.groupMgr.AddGroup(ctx, group)
2377 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002378 if err != nil {
2379 errorsList = append(errorsList, err)
2380 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002381 }
2382 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002383 // err = dh.groupMgr.ModifyGroup(ctx, group)
2384 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002385 if err != nil {
2386 errorsList = append(errorsList, err)
2387 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002388 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002389 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002390 // err = dh.groupMgr.DeleteGroup(ctx, group)
2391 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002392 if err != nil {
2393 errorsList = append(errorsList, err)
2394 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002395 }
2396 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002397
2398 return errorsList
2399}
2400
Mahir Gunyela2e68702022-12-07 00:00:42 -08002401// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002402func (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 -07002403 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002404
2405 if dh.getDeviceDeletionInProgressFlag() {
2406 // The device itself is going to be reset as part of deletion. So nothing to be done.
2407 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2408 return nil
2409 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302410 if dh.transitionMap.currentDeviceState != deviceStateUp {
2411 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2412 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2413 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002414 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2415 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2416 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002417 if len(errorsList) > 0 {
2418 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2419 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002420 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002421 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302422}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002423
Mahir Gunyela2e68702022-12-07 00:00:42 -08002424// DisableDevice disables the given device
2425// It marks the following for the given device:
2426// Device-Handler Admin-State : down
2427// Device Port-State: UNKNOWN
2428// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002430 /* On device disable ,admin state update has to be done prior sending request to agent since
2431 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002432 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302433 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2434 if _, err := dh.Client.DisableOlt(subCtx, new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002435 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302436 cancel()
Girish Kumarf26e4882020-03-05 06:49:10 +00002437 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002438 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002439 }
bseenivaa1622112025-12-11 18:24:02 +05302440 cancel()
Chaitrashree G S44124192019-08-07 20:21:36 -04002441 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002442 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002443 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002444 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302445
2446 dh.discOnus = sync.Map{}
2447 dh.onus = sync.Map{}
2448
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002449 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302450 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002451 if dh.isCollectorActive {
2452 dh.stopCollector <- true
2453 }
2454 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302455
Neha Sharma96b7bf22020-06-15 10:37:32 +00002456 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002457 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302458 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302459 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002460
kdarapu1afeceb2020-02-12 01:38:09 -05002461 // 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 -04002462 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002463 DeviceId: cloned.Id,
2464 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2465 OperStatus: voltha.OperStatus_UNKNOWN,
2466 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002467 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002468 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002469 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002470 return nil
2471}
2472
Neha Sharma96b7bf22020-06-15 10:37:32 +00002473func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002474 // Update onu state as unreachable in onu adapter
2475 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302476 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002477
Akash Kankanala041a2122024-10-16 15:49:22 +05302478 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002479 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002480 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002481 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 -04002482 }
2483 if onuDevices != nil {
2484 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002485 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002486 DeviceId: onuDevice.Id,
2487 OnuIndication: &onuInd,
2488 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002489 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002490 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002491 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002492 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002493 }
2494 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002495}
2496
Mahir Gunyela2e68702022-12-07 00:00:42 -08002497// ReenableDevice re-enables the olt device after disable
2498// It marks the following for the given device:
2499// Device-Handler Admin-State : up
2500// Device Port-State: ACTIVE
2501// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302503 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302504 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2505 if _, err := dh.Client.ReenableOlt(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302506 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302507 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302508 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2509 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302510 }
bseenivaa1622112025-12-11 18:24:02 +05302511 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302512 } else {
2513 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 +05302514 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002515 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002516
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002517 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002518 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002519 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002520 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002521 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2522 } else {
2523 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2524 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2525 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002526 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002527 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302528 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002529 device.OperStatus = voltha.OperStatus_ACTIVE
2530 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302531 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002532 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002533 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002534 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002535
khenaidoodc2116e2021-10-19 17:33:19 -04002536 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002537 DeviceId: device.Id,
2538 OperStatus: device.OperStatus,
2539 ConnStatus: device.ConnectStatus,
2540 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302541 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002542 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002543 "connect-status": device.ConnectStatus,
2544 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002545 }
kesavand39e0aa32020-01-28 20:58:50 -05002546
Neha Sharma96b7bf22020-06-15 10:37:32 +00002547 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002548
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002549 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002550}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002551
npujarec5762e2020-01-01 14:08:48 +05302552func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002553 var uniID uint32
2554 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002555 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302556 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002557 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002558 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002559 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002560 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2561 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2562 } else {
2563 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2564 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002565 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002566 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002567 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002568 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002569 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002570 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002571 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002572 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002573 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002574 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002575 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002576 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002577 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002578 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002579 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002580 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302581 }
yasin saplibddc2d72022-02-08 13:10:17 +00002582 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2583 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002584 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002585 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302586 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002587 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002588 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002589 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 -03002590 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002591 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002592 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002593 if len(errs) > 0 {
2594 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2595 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2596 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002597 return nil
2598}
2599
Devmalya Paul495b94a2019-08-27 19:42:00 -04002600// 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 +05302601func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002602 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002603 /* Clear the KV store data associated with the all the UNI ports
2604 This clears up flow data and also resource map data for various
2605 other pon resources like alloc_id and gemport_id
2606 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002607
Abhay Kumarb87ac882025-10-30 09:55:07 +00002608 if dh.getDeviceDeletionInProgressFlag() {
2609 logger.Errorw(ctx, "cannot complete operation as device deletion is in progress", log.Fields{"device-id": dh.device.Id})
2610 return olterrors.NewErrAdapter(fmt.Errorf("cannot complete operation as device deletion is in progress").Error(), log.Fields{"device-id": dh.device.Id}, nil)
2611 }
2612
Girish Gowdra950326e2021-11-05 12:43:24 -07002613 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002614 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002615
Himani Chawla49a5d562020-11-25 11:53:44 +05302616 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002617 // Stop the Stats collector
2618 if dh.isCollectorActive {
2619 dh.stopCollector <- true
2620 }
2621 // stop the heartbeat check routine
2622 if dh.isHeartbeatCheckActive {
2623 dh.stopHeartbeatCheck <- true
2624 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302625 // Stop the read indication only if it the routine is active
2626 if dh.isReadIndicationRoutineActive {
2627 dh.stopIndications <- true
2628 }
2629 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302630
2631 err := dh.cleanupDeviceResources(ctx)
2632 if err != nil {
2633 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2634 } else {
2635 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2636 }
2637
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002638 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302639 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002640 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302641 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2642 if _, err = dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002643 go func() {
2644 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302645 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2646 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002647 }
2648 }()
2649 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002650 }
bseenivaa1622112025-12-11 18:24:02 +05302651 cancel()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002652 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002653 // There is no need to update the core about operation status and connection status of the OLT.
2654 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2655 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2656 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002657
khenaidoo7eb2d672021-10-22 19:08:50 -04002658 // Stop the adapter grpc clients for that parent device
2659 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002660 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002661}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002662
2663// StopAllFlowRoutines stops all flow routines
2664func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2665 var wg sync.WaitGroup
2666 wg.Add(1) // for the mcast routine below to finish
2667 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2668 for _, flMgr := range dh.flowMgr {
2669 if flMgr != nil {
2670 wg.Add(1) // for the flow handler routine below to finish
2671 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2672 }
2673 }
2674 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2675 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2676 } else {
2677 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2678 }
2679}
2680
Gustavo Silva41af9122022-10-11 11:05:13 -03002681func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2682 var errs []error
Abhay Kumarb87ac882025-10-30 09:55:07 +00002683 if dh.resourceMgr != nil && dh.totalPonPorts > 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302684 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002685 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002686 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002687 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002688 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002689 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2690 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302691 }
2692 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002693 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2694 errs = append(errs, err)
2695 }
2696 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2697 errs = append(errs, err)
2698 }
2699 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2700 errs = append(errs, err)
2701 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002702 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002703 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002704 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002705 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002706 }
2707 // Clean up NNI manager's data
2708 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2709 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002710 }
A R Karthick1f85b802019-10-11 05:06:05 +00002711
Abhay Kumarb87ac882025-10-30 09:55:07 +00002712 logger.Debugw(ctx, "lockDevice for KVStore close client", log.Fields{"deviceID": dh.device.Id})
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002713 dh.CloseKVClient(ctx)
2714
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002715 // Take one final sweep at cleaning up KV store for the OLT device
2716 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002717 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2718 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002719 }
2720
Devmalya Paul495b94a2019-08-27 19:42:00 -04002721 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302722 dh.onus.Range(func(key interface{}, value interface{}) bool {
2723 dh.onus.Delete(key)
2724 return true
2725 })
2726
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002727 /*Delete discovered ONU map for the device*/
2728 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2729 dh.discOnus.Delete(key)
2730 return true
2731 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002732 if len(errs) > 0 {
2733 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2734 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2735 }
2736 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002737}
2738
Mahir Gunyela2e68702022-12-07 00:00:42 -08002739// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002740func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302741 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302742 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2743 defer cancel()
2744 if _, err := dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302745 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2746 }
2747 } else {
2748 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 -04002749 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302750
Neha Sharma96b7bf22020-06-15 10:37:32 +00002751 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002752 return nil
2753}
2754
David K. Bainbridge794735f2020-02-11 21:01:37 -08002755func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002756 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002757 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002758 "packet-indication": *packetIn,
2759 "device-id": dh.device.Id,
2760 "packet": hex.EncodeToString(packetIn.Pkt),
2761 })
2762 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002763 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2764 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2765 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002766 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002767 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002768 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002769 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002770 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002771 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002772 "logical-port-num": logicalPortNum,
2773 "device-id": dh.device.Id,
2774 "packet": hex.EncodeToString(packetIn.Pkt),
2775 })
2776 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777
khenaidoodc2116e2021-10-19 17:33:19 -04002778 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002779 DeviceId: dh.device.Id,
2780 Port: logicalPortNum,
2781 Packet: packetIn.Pkt,
2782 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302783 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002784 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302785 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002786 "device-id": dh.device.Id,
2787 "packet": hex.EncodeToString(packetIn.Pkt),
2788 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002789 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002790
Matteo Scandolo92186242020-06-12 10:54:18 -07002791 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002792 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002793 "packet": hex.EncodeToString(packetIn.Pkt),
2794 "device-id": dh.device.Id,
2795 })
2796 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002797 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002798}
2799
Mahir Gunyela2e68702022-12-07 00:00:42 -08002800// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2801func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2802 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2803 if err != nil {
2804 return olterrors.NewErrInvalidValue(log.Fields{
2805 "egress-nni-port": egressPortNo,
2806 "device-id": dh.device.Id,
2807 }, err)
2808 }
2809 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2810
2811 if logger.V(log.DebugLevel) {
2812 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2813 "uplink-pkt": uplinkPkt,
2814 "packet": hex.EncodeToString(packet.Data),
2815 "device-id": dh.device.Id,
2816 })
2817 }
2818
bseenivaa1622112025-12-11 18:24:02 +05302819 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2820 defer cancel()
2821 if _, err := dh.Client.UplinkPacketOut(subCtx, &uplinkPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002822 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2823 "packet": hex.EncodeToString(packet.Data),
2824 "device-id": dh.device.Id,
2825 }, err)
2826 }
2827 return nil
2828}
2829
2830// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2831func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2832 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2833 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2834 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2835 // Do not packet-out lldp packets on uni port.
2836 // ONOS has no clue about uni/nni ports, it just packets out on all
2837 // available ports on the Logical Switch. It should not be interested
2838 // in the UNI links.
2839 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2840 "device-id": dh.device.Id,
2841 })
2842 return nil
2843 }
2844 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2845 if innerEthType == 0x8100 {
2846 // q-in-q 802.1ad or 802.1q double tagged packet.
2847 // slice out the outer tag.
2848 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2849 if logger.V(log.DebugLevel) {
2850 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2851 "packet-data": hex.EncodeToString(packet.Data),
2852 "device-id": dh.device.Id,
2853 })
2854 }
2855 }
2856 }
2857 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2858 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2859 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2860 var gemPortID uint32
2861 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2862 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2863 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2864 }
2865 if err != nil {
2866 // In this case the openolt agent will receive the gemPortID as 0.
2867 // The agent tries to retrieve the gemPortID in this case.
2868 // This may not always succeed at the agent and packetOut may fail.
2869 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2870 "intf-id": intfID,
2871 "onu-id": onuID,
2872 "uni-id": uniID,
2873 "packet": hex.EncodeToString(packet.Data),
2874 "device-id": dh.device.Id,
2875 "error": err,
2876 })
2877 }
2878
2879 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2880 if logger.V(log.DebugLevel) {
2881 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2882 "egress-port-no": egressPortNo,
2883 "intf-id": intfID,
2884 "onu-id": onuID,
2885 "uni-id": uniID,
2886 "gem-port-id": gemPortID,
2887 "packet": hex.EncodeToString(packet.Data),
2888 "device-id": dh.device.Id,
2889 })
2890 }
2891
bseenivaa1622112025-12-11 18:24:02 +05302892 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2893 defer cancel()
2894 if _, err := dh.Client.OnuPacketOut(subCtx, &onuPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002895 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2896 "source": "adapter",
2897 "destination": "onu",
2898 "egress-port-number": egressPortNo,
2899 "intf-id": intfID,
2900 "oni-id": onuID,
2901 "uni-id": uniID,
2902 "gem-port-id": gemPortID,
2903 "packet": hex.EncodeToString(packet.Data),
2904 "device-id": dh.device.Id,
2905 }, err)
2906 }
2907 return nil
2908}
2909
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002910// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002911func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002912 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002913 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002914 "device-id": dh.device.Id,
2915 "egress-port-no": egressPortNo,
2916 "pkt-length": len(packet.Data),
2917 "packet": hex.EncodeToString(packet.Data),
2918 })
2919 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002920
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002921 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002922 var err error
mgouda86543582025-10-29 20:58:16 +05302923 switch egressPortType {
2924 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002925 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302926 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002927 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302928 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002929 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302930 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002931 "egressPortType": egressPortType,
2932 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302933 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002934 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002935 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002936 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002937}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002938
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002939func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2940 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002941}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302942
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002943func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002944 defer func() {
2945 dh.lockDevice.Lock()
2946 dh.isHeartbeatCheckActive = false
2947 dh.lockDevice.Unlock()
2948 }()
2949
2950 dh.lockDevice.Lock()
2951 dh.isHeartbeatCheckActive = true
2952 dh.lockDevice.Unlock()
2953
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302954 // start the heartbeat check towards the OLT.
2955 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302956 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302957
2958 for {
2959 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2960 select {
2961 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002962 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002963 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002964 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302965 if timerCheck == nil {
2966 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002967 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302968 }
2969 } else {
2970 if timerCheck != nil {
2971 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002972 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302973 }
2974 timerCheck = nil
2975 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302976 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2977 if dh.heartbeatSignature == 0 {
2978 // First time the signature will be 0, update the signture to DB when not found.
2979 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2980 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2981 }
2982 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2983
2984 dh.lockDevice.RLock()
2985 // Stop the read indication only if it the routine is active
2986 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2987 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2988 // on next execution of the readIndication routine.
2989 if !dh.isReadIndicationRoutineActive {
2990 // Start reading indications
2991 go func() {
2992 if err = dh.readIndications(ctx); err != nil {
2993 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2994 }
2995 }()
2996 }
2997 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302998 } else {
2999 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
3000 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
3001 dh.heartbeatSignature = heartBeat.HeartbeatSignature
3002 go dh.updateStateRebooted(ctx)
3003 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303004 }
3005 cancel()
3006 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003007 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303008 return
3009 }
3010 }
3011}
3012
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003013func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04003014 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003015 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07003016 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3017 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3018 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3019 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3020 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003021 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07003022 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3023 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003024 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303025
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303026 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003027 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003028 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04003029 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04003030 DeviceId: dh.device.Id,
3031 OperStatus: voltha.OperStatus_UNKNOWN,
3032 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
3033 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003034 _ = 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 -04003035 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303036 /*
3037 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
3038 DeviceId: dh.device.Id,
3039 PortTypeFilter: 0,
3040 OperStatus: voltha.OperStatus_UNKNOWN,
3041 }); err != nil {
3042 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3043 }
3044 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003045
Akash Kankanala041a2122024-10-16 15:49:22 +05303046 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003047 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003048 cloned := proto.Clone(device).(*voltha.Device)
3049 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3050 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3051 dh.device = cloned // update local copy of the device
3052 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003053
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003054 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003055 // Stop the Stats collector
3056 if dh.isCollectorActive {
3057 dh.stopCollector <- true
3058 }
3059 // stop the heartbeat check routine
3060 if dh.isHeartbeatCheckActive {
3061 dh.stopHeartbeatCheck <- true
3062 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003063 // Stop the read indication only if it the routine is active
3064 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3065 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3066 // on next execution of the readIndication routine.
3067 if dh.isReadIndicationRoutineActive {
3068 dh.stopIndications <- true
3069 }
3070 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003071 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303072 }
3073}
kesavand39e0aa32020-01-28 20:58:50 -05003074
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303075func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3076 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3077 if err != nil || device == nil {
3078 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3079 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3080 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3081 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3082 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3083 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3084 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3085 return
3086 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303087 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003088 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303089
3090 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3091 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303092 // First, stop the read indication and heartbeat check routines to prevent any delay
3093 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303094 dh.lockDevice.RLock()
3095 // Stop the read indication only if it the routine is active
3096 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3097 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3098 // on next execution of the readIndication routine.
3099 if dh.isReadIndicationRoutineActive {
3100 dh.stopIndications <- true
3101 }
3102 dh.lockDevice.RUnlock()
3103
bseenivad1c984b2025-01-09 12:54:44 +05303104 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3105 DeviceId: dh.device.Id,
3106 OperStatus: voltha.OperStatus_REBOOTED,
3107 ConnStatus: voltha.ConnectStatus_REACHABLE,
3108 }); err != nil {
3109 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3110 }
3111
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303112 //raise olt communication failure event
3113 raisedTs := time.Now().Unix()
3114 cloned := proto.Clone(device).(*voltha.Device)
3115 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3116 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3117 dh.device = cloned // update local copy of the device
3118 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3119
Gustavo Silva41af9122022-10-11 11:05:13 -03003120 if err := dh.cleanupDeviceResources(ctx); err != nil {
3121 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3122 } else {
3123 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3124 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003125
3126 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303127 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003128 if dh.isCollectorActive {
3129 dh.stopCollector <- true
3130 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303131 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003132 if dh.isHeartbeatCheckActive {
3133 dh.stopHeartbeatCheck <- true
3134 }
3135 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303136
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003137 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303138
Akash Kankanala041a2122024-10-16 15:49:22 +05303139 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303140 dh.adapterPreviouslyConnected = false
3141 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303142 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3143 if err != nil || childDevices == nil {
3144 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3145 continue
3146 }
3147 if len(childDevices.Items) == 0 {
3148 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3149 break
3150 } else {
3151 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3152 time.Sleep(5 * time.Second)
3153 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303154 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303155 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003156 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303157 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3158 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303159}
3160
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303161// EnableOnuSerialNumber to enable onu serial number
3162func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3163 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3164 onuSerialNumber := device.SerialNumber
3165
3166 // fetch interfaceid from PortNo
3167 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3168
3169 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3170 if err != nil {
3171 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3172 log.Fields{
3173 "devicer-id": dh.device.Id,
3174 "serial-number": onuSerialNumber}, err).Log()
3175 }
3176
3177 onuIntf := &oop.InterfaceOnuSerialNumber{
3178 IntfId: ponID,
3179 OnuSerialNumber: sn,
3180 }
3181 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3182
3183 if err != nil {
3184 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3185 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3186 "device-id": dh.device.Id,
3187 "onu-serial-number": onuSerialNumber}, err)
3188 }
3189 return nil
3190}
3191
3192// DisableOnuSerialNumber to disable onu serial number
3193func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3194 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3195 onuSerialNumber := device.SerialNumber
3196 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3197 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3198 if err != nil {
3199 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3200 log.Fields{
3201 "devicer-id": dh.device.Id,
3202 "serial-number": onuSerialNumber}, err).Log()
3203 }
3204
3205 onuIntf := &oop.InterfaceOnuSerialNumber{
3206 OnuSerialNumber: sn,
3207 IntfId: ponID,
3208 }
3209 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3210
3211 if err != nil {
3212 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3213 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3214 "device-id": dh.device.Id,
3215 "onu-serial-number": onuSerialNumber}, err)
3216 }
3217 return nil
3218}
3219
3220// EnableOnu to enable onu
3221func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3222 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3223 onuSerialNumber := device.SerialNumber
3224 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3225 if InCacheOnuDev == nil {
3226 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3227 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3228 "device-id": dh.device.Id,
3229 "onu-serial-number": onuSerialNumber}, nil)
3230 }
3231 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})
3232
3233 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3234 if err != nil {
3235 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3236 log.Fields{
3237 "device-id": dh.device.Id,
3238 "serial-number": onuSerialNumber}, err).Log()
3239 }
3240
3241 onuIntf := &oop.InterfaceOnuSerialNumber{
3242 OnuSerialNumber: sn,
3243 IntfId: InCacheOnuDev.intfID,
3244 }
3245 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3246 OnuId: InCacheOnuDev.onuID,
3247 IntfIdSerialNum: onuIntf,
3248 }
3249 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3250
3251 if err != nil {
3252 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3253 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3254 "olt-device-id": dh.device.Id,
3255 "onu-serial-number": onuSerialNumber}, err)
3256 }
3257 return nil
3258}
3259
3260// DisableOnu to disable onu
3261func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3262 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3263 onuSerialNumber := device.SerialNumber
3264 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3265 if InCacheOnuDev == nil {
3266 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3267 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3268 "device-id": dh.device.Id,
3269 "onu-serial-number": onuSerialNumber}, nil)
3270 }
3271 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})
3272
3273 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3274 if err != nil {
3275 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3276 log.Fields{
3277 "device-id": dh.device.Id,
3278 "serial-number": onuSerialNumber}, err).Log()
3279 }
3280
3281 onuIntf := &oop.InterfaceOnuSerialNumber{
3282 OnuSerialNumber: sn,
3283 IntfId: InCacheOnuDev.intfID,
3284 }
3285 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3286 OnuId: InCacheOnuDev.onuID,
3287 IntfIdSerialNum: onuIntf,
3288 }
3289 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3290
3291 if err != nil {
3292 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3293 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3294 "olt-device-id": dh.device.Id,
3295 "onu-serial-number": onuSerialNumber}, err)
3296 }
3297 return nil
3298}
3299
kesavand39e0aa32020-01-28 20:58:50 -05003300// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003301func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3302 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3303 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003304}
3305
3306// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003307func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3308 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3309 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003310}
3311
Mahir Gunyela2e68702022-12-07 00:00:42 -08003312// 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 +00003313func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3314 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003315 if port.GetType() == voltha.Port_ETHERNET_NNI {
3316 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003317 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303318 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303319 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003320 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003321 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003322 }
3323 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003324 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003325 ponIntf := &oop.Interface{IntfId: ponID}
3326 var operStatus voltha.OperStatus_Types
bseenivaa1622112025-12-11 18:24:02 +05303327 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
kesavand39e0aa32020-01-28 20:58:50 -05003328 if enablePort {
3329 operStatus = voltha.OperStatus_ACTIVE
bseenivaa1622112025-12-11 18:24:02 +05303330 out, err := dh.Client.EnablePonIf(subCtx, ponIntf)
3331 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003332 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303333 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003334 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003335 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003336 }
3337 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003338 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003339 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003340 } else {
3341 operStatus = voltha.OperStatus_UNKNOWN
bseenivaa1622112025-12-11 18:24:02 +05303342 out, err := dh.Client.DisablePonIf(subCtx, ponIntf)
3343 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003344 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303345 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003346 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003347 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003348 }
3349 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003350 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003351 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003352 }
khenaidoodc2116e2021-10-19 17:33:19 -04003353 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003354 DeviceId: dh.device.Id,
3355 PortType: voltha.Port_PON_OLT,
3356 PortNo: port.PortNo,
3357 OperStatus: operStatus,
3358 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303359 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303360 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003361 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003362 }
3363 return nil
3364}
3365
Mahir Gunyela2e68702022-12-07 00:00:42 -08003366// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003367func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003368 // Disable the port and update the oper_port_status to core
3369 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003370 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003371 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003372 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303373 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303374 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003375 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003376 }
3377 }
3378 }
3379 return nil
3380}
3381
Mahir Gunyela2e68702022-12-07 00:00:42 -08003382// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003383func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3384 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3385 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003386 if port.Type == voltha.Port_ETHERNET_NNI {
3387 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003388 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003389 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003390 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003391 }
3392 }
3393 if port.Type == voltha.Port_PON_OLT {
3394 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003395 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003396 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003397 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003398 }
3399 }
3400 }
3401}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003402
3403// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003404func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003405 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003406 if dh.getDeviceDeletionInProgressFlag() {
3407 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3408 // will reboot, so everything will be reset on the pOLT too.
3409 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3410 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3411 return nil
3412 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303413
3414 if dh.transitionMap.currentDeviceState != deviceStateUp {
3415 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})
3416 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3417 }
3418
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003419 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003420 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003421
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003422 var sn *oop.SerialNumber
3423 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003424 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303425 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003426 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303427 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003428 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003429 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003430
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003431 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303432 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003433 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003434 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3435 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3436 "device-id": dh.device.Id,
3437 "intf-id": intfID,
3438 "onuID": onuID,
3439 "err": err})
3440 } else {
3441 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003442 // Delete flows from device before schedulers and queue
3443 // Clear flowids for gem cache.
3444 removedFlows := []uint64{}
3445 for _, gem := range onuGem.GemPorts {
3446 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3447 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303448 // multiple gem port can have the same flow id
3449 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003450 var alreadyRemoved bool
3451 for _, removedFlowID := range removedFlows {
3452 if removedFlowID == flowID {
3453 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3454 alreadyRemoved = true
3455 break
3456 }
3457 }
3458 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003459 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003460 removedFlows = appendUnique64bit(removedFlows, flowID)
3461 }
3462 }
3463 }
3464 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3465 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003466 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3467 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3468 "device-id": dh.device.Id,
3469 "onu-device": onu,
3470 "err": err})
3471 }
yasin saplibddc2d72022-02-08 13:10:17 +00003472 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003473 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3474 "intf-id": intfID,
3475 "onu-device": onu,
3476 "onu-gem": onuGem,
3477 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303478 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003479 }
3480 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003481 }
yasin saplibddc2d72022-02-08 13:10:17 +00003482 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003483 dh.onus.Delete(onuKey)
3484 dh.discOnus.Delete(onuSn)
3485
bseenivaa1622112025-12-11 18:24:02 +05303486 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003487 // Now clear the ONU on the OLT
bseenivaa1622112025-12-11 18:24:02 +05303488 if _, err := dh.Client.DeleteOnu(subCtx, onu); err != nil {
3489 cancel()
Thomas Lee S94109f12020-03-03 16:39:29 +05303490 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303491 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003492 "onu-id": onuID}, err).Log()
3493 }
bseenivaa1622112025-12-11 18:24:02 +05303494 cancel()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003495 return nil
3496}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003497func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3498 flow := &oop.Flow{FlowId: flowID}
3499 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3500 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3501 "device-id": dh.device.Id})
3502 } else {
3503 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3504 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3505 "device-id": dh.device.Id,
3506 "err": err})
3507 }
3508 }
3509}
Girish Gowdracefae192020-03-19 18:14:10 -07003510
3511func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003512 for _, field := range flow_utils.GetOfbFields(flow) {
3513 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003514 return field.GetPort()
3515 }
3516 }
3517 return InvalidPort
3518}
3519
3520func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003521 for _, action := range flow_utils.GetActions(flow) {
3522 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003523 if out := action.GetOutput(); out != nil {
3524 return out.GetPort()
3525 }
3526 }
3527 }
3528 return InvalidPort
3529}
3530
Girish Gowdracefae192020-03-19 18:14:10 -07003531func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3532 inPort := getInPortFromFlow(flow)
3533 outPort := getOutPortFromFlow(flow)
3534
3535 if inPort == InvalidPort || outPort == InvalidPort {
3536 return inPort, outPort
3537 }
3538
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003539 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003540 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003541 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003542 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003543 return uniPort, outPort
3544 }
3545 }
3546 } else {
3547 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003548 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003549 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003550 return inPort, uniPort
3551 }
3552 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003553 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003554 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003555 return uniPort, outPort
3556 }
3557 }
3558 }
3559
3560 return InvalidPort, InvalidPort
3561}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003562
3563func extractOmciTransactionID(omciPkt []byte) uint16 {
3564 if len(omciPkt) > 3 {
3565 d := omciPkt[0:2]
3566 transid := binary.BigEndian.Uint16(d)
3567 return transid
3568 }
3569 return 0
3570}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003571
3572// StoreOnuDevice stores the onu parameters to the local cache.
3573func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3574 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3575 dh.onus.Store(onuKey, onuDevice)
3576}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003577
khenaidoodc2116e2021-10-19 17:33:19 -04003578func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003579 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003580 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003581 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003582 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003583 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003584 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003585 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003586 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3587 return nil, err
3588 }
3589 ID = device.ProxyAddress.GetOnuId()
3590 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3591 valueparam.Onu = &Onu
3592 valueparam.Value = value
3593
3594 // This API is unsupported until agent patch is added
3595 resp.Unsupported = uint32(value)
3596 _ = ctx
3597
3598 // Uncomment this code once agent changes are complete and tests
3599 /*
3600 resp, err = dh.Client.GetValue(ctx, valueparam)
3601 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003602 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003603 return nil, err
3604 }
3605 */
3606
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003607 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 -08003608 return resp, nil
3609}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003610
Akash Kankanala041a2122024-10-16 15:49:22 +05303611func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003612 // Default to NNI
3613 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003614 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003615 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003616 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003617 }
3618 return intfID
3619}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003620
Akash Kankanala041a2122024-10-16 15:49:22 +05303621func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003622 dh.perPonOnuIndicationChannelLock.Lock()
3623 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3624 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003625 return ch.indicationChannel
3626 }
3627 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303628 // We create a buffered channel here to avoid calling function to be blocked
3629 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003630 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003631 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003632 stopChannel: make(chan struct{}),
3633 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003634 dh.perPonOnuIndicationChannel[intfID] = channels
3635 dh.perPonOnuIndicationChannelLock.Unlock()
3636 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003637 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003638}
3639
Mahir Gunyelb0046752021-02-26 13:51:05 -08003640func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3641 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3642 dh.perPonOnuIndicationChannelLock.Lock()
3643 defer dh.perPonOnuIndicationChannelLock.Unlock()
3644 for _, v := range dh.perPonOnuIndicationChannel {
3645 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003646 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003647 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003648}
3649
Mahir Gunyelb0046752021-02-26 13:51:05 -08003650func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3651 ind := onuIndicationMsg{
3652 ctx: ctx,
3653 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003654 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003655 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003656 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303657 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003658}
3659
Mahir Gunyelb0046752021-02-26 13:51:05 -08003660func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003661 for {
3662 select {
3663 // process one indication per onu, before proceeding to the next one
3664 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003665 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003666 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003667 "ind": indication})
3668 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003669 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003670 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003671 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3672 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003673 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003674 }
3675 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003676 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003677 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3678 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003679 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003680 }
3681 }
3682 case <-onuChannels.stopChannel:
3683 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3684 close(onuChannels.indicationChannel)
3685 return
3686 }
3687 }
3688}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003689
3690// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3691// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003692func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003693 if dh.getDeviceDeletionInProgressFlag() {
3694 // The device itself is going to be reset as part of deletion. So nothing to be done.
3695 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3696 return nil
3697 }
3698
Girish Gowdra491a9c62021-01-06 16:43:07 -08003699 // Step1 : Fill McastFlowOrGroupControlBlock
3700 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3701 // Step3 : Wait on response channel for response
3702 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003703 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003704 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3705 errChan := make(chan error)
3706 var groupID uint32
3707 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3708 ctx: ctx,
3709 flowOrGroupAction: action,
3710 flow: flow,
3711 group: group,
3712 errChan: &errChan,
3713 }
3714 if flow != nil {
3715 groupID = flow_utils.GetGroup(flow)
3716 } else if group != nil {
3717 groupID = group.Desc.GroupId
3718 } else {
3719 return errors.New("flow-and-group-both-nil")
3720 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003721 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3722 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3723 // Derive the appropriate go routine to handle the request by a simple module operation.
3724 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3725 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3726 // Wait for handler to return error value
3727 err := <-errChan
3728 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3729 return err
3730 }
3731 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3732 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003733}
3734
3735// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003736func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003737 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003738 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003739 // block on the channel to receive an incoming mcast flow/group
3740 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003741 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3742 if mcastFlowOrGroupCb.flow != nil {
3743 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3744 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3745 log.Fields{"device-id": dh.device.Id,
3746 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003747 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3748 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3749 for _, flMgr := range dh.flowMgr {
3750 if flMgr != nil {
3751 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3752 break
3753 }
3754 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003755 // Pass the return value over the return channel
3756 *mcastFlowOrGroupCb.errChan <- err
3757 } else { // flow remove
3758 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3759 log.Fields{"device-id": dh.device.Id,
3760 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003761 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3762 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3763 for _, flMgr := range dh.flowMgr {
3764 if flMgr != nil {
3765 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3766 break
3767 }
3768 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003769 // Pass the return value over the return channel
3770 *mcastFlowOrGroupCb.errChan <- err
3771 }
3772 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303773 switch mcastFlowOrGroupCb.flowOrGroupAction {
3774 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003775 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3776 log.Fields{"device-id": dh.device.Id,
3777 "groupToAdd": mcastFlowOrGroupCb.group})
3778 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3779 // Pass the return value over the return channel
3780 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303781 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003782 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3783 log.Fields{"device-id": dh.device.Id,
3784 "groupToModify": mcastFlowOrGroupCb.group})
3785 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3786 // Pass the return value over the return channel
3787 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303788 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003789 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3790 log.Fields{"device-id": dh.device.Id,
3791 "groupToRemove": mcastFlowOrGroupCb.group})
3792 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3793 // Pass the return value over the return channel
3794 *mcastFlowOrGroupCb.errChan <- err
3795 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003796 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003797 case <-stopHandler:
3798 dh.mcastHandlerRoutineActive[routineIndex] = false
3799 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003800 }
3801 }
3802}
kesavand62126212021-01-12 04:56:06 -05003803
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003804// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003805func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003806 for i, v := range dh.stopMcastHandlerRoutine {
3807 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003808 select {
3809 case v <- true:
3810 case <-time.After(time.Second * 5):
3811 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3812 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003813 }
3814 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003815
3816 if dh.incomingMcastFlowOrGroup != nil {
3817 for k := range dh.incomingMcastFlowOrGroup {
3818 if dh.incomingMcastFlowOrGroup[k] != nil {
3819 dh.incomingMcastFlowOrGroup[k] = nil
3820 }
3821 }
3822 dh.incomingMcastFlowOrGroup = nil
3823 }
3824
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003825 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003826 logger.Debug(ctx, "stopped all mcast handler routines")
3827}
3828
Akash Kankanala041a2122024-10-16 15:49:22 +05303829// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003830func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003831 singleValResp := extension.SingleGetValueResponse{
3832 Response: &extension.GetValueResponse{
3833 Response: &extension.GetValueResponse_PortCoutners{
3834 PortCoutners: &extension.GetOltPortCountersResponse{},
3835 },
3836 },
3837 }
3838
Akash Kankanala041a2122024-10-16 15:49:22 +05303839 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003840 return &extension.SingleGetValueResponse{
3841 Response: &extension.GetValueResponse{
3842 Status: status,
3843 ErrReason: reason,
3844 },
3845 }
3846 }
3847
3848 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3849 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303850 // send error response
kesavand62126212021-01-12 04:56:06 -05003851 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3852 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3853 }
3854 statIndChn := make(chan bool, 1)
3855 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3856 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303857 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003858
3859 go func() {
bseenivaa1622112025-12-11 18:24:02 +05303860 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3861 _, err := dh.Client.CollectStatistics(subCtx, new(oop.Empty))
kesavand62126212021-01-12 04:56:06 -05003862 if err != nil {
3863 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3864 }
bseenivaa1622112025-12-11 18:24:02 +05303865 cancel()
kesavand62126212021-01-12 04:56:06 -05003866 }()
3867 select {
3868 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303869 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003870 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3871 case <-time.After(oltPortInfoTimeout * time.Second):
3872 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3873 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3874 case <-ctx.Done():
3875 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3876 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3877 }
mgouda86543582025-10-29 20:58:16 +05303878 switch oltPortInfo.PortType {
3879 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303880 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003881 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003882 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3883 cmnni := dh.portStats.collectNNIMetrics(intfID)
3884 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303885 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003886 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3887 }
3888 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3889 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303890 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003891 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003892 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003893 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3894 cmpon := dh.portStats.collectPONMetrics(intfID)
3895 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303896 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003897 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3898 }
3899 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3900 return &singleValResp
3901 }
3902 }
3903 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3904}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303905
Akash Kankanala041a2122024-10-16 15:49:22 +05303906//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303907func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303908 singleValResp := extension.SingleGetValueResponse{
3909 Response: &extension.GetValueResponse{
3910 Status: extension.GetValueResponse_OK,
3911 Response: &extension.GetValueResponse_OffloadedAppsStats{
3912 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3913 },
3914 },
3915 }
3916
3917 return &singleValResp
3918}
3919
Akash Kankanala041a2122024-10-16 15:49:22 +05303920//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303921func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303922 singleValResp := extension.SingleSetValueResponse{
3923 Response: &extension.SetValueResponse{
3924 Status: extension.SetValueResponse_OK,
3925 },
3926 }
3927
3928 return &singleValResp
3929}
3930
Akash Kankanala041a2122024-10-16 15:49:22 +05303931//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303932func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303933 singleValResp := extension.SingleSetValueResponse{
3934 Response: &extension.SetValueResponse{
3935 Status: extension.SetValueResponse_OK,
3936 },
3937 }
3938
3939 return &singleValResp
3940}
3941
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303942func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303943 singleValResp := extension.SingleGetValueResponse{
3944 Response: &extension.GetValueResponse{
3945 Response: &extension.GetValueResponse_OnuPonCounters{
3946 OnuPonCounters: &extension.GetOnuCountersResponse{},
3947 },
3948 },
3949 }
3950
Akash Kankanala041a2122024-10-16 15:49:22 +05303951 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303952 return &extension.SingleGetValueResponse{
3953 Response: &extension.GetValueResponse{
3954 Status: status,
3955 ErrReason: reason,
3956 },
3957 }
3958 }
3959 intfID := onuPonInfo.IntfId
3960 onuID := onuPonInfo.OnuId
3961 onuKey := dh.formOnuKey(intfID, onuID)
3962
3963 if _, ok := dh.onus.Load(onuKey); !ok {
3964 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3965 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3966 }
3967 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3968 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3969 if cmnni == nil {
3970 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3971 }
3972 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3973 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303974}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003975
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303976func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3977 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3978 if err != nil {
3979 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3980 return nil, err
3981 }
3982 if onuGemInfo != nil {
3983 if len(onuGemInfo.UniPorts) == 0 {
3984 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3985 return nil, err
3986 }
3987 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3988 return onuGemInfo, nil
3989 }
3990 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3991 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3992}
3993
3994func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3995 var err error
3996 var allocStats *oop.OnuAllocIdStatistics
3997 var onuGemStats *oop.GemPortStatistics
3998 for _, uni := range onuGemInfo.UniPorts {
3999 uniID := plt.UniIDFromPortNum(uni)
4000 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
4001 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
4002 if len(tpIDs) == 0 {
4003 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
4004 continue
4005 }
4006 for _, tpId := range tpIDs {
4007 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
4008 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
4009 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
4010 if techProfileInstance != nil {
4011 switch tpInst := techProfileInstance.(type) {
4012 case *tp_pb.TechProfileInstance:
4013 allocId := tpInst.UsScheduler.AllocId
4014 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
bseenivaa1622112025-12-11 18:24:02 +05304015 allocCtx, allocCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4016 allocStats, err = dh.Client.GetAllocIdStatistics(allocCtx, &onuAllocPkt)
4017 allocCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304018 if err != nil {
4019 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
4020 return err
4021 }
4022 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
4023 allocIdInfo.AllocId = allocStats.AllocId
4024 allocIdInfo.RxBytes = allocStats.RxBytes
4025
4026 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
4027
4028 gemPorts := tpInst.UpstreamGemPortAttributeList
4029 for _, gem := range gemPorts {
4030 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
bseenivaa1622112025-12-11 18:24:02 +05304031 gemCtx, gemCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4032 onuGemStats, err = dh.Client.GetGemPortStatistics(gemCtx, &onuGemPkt)
4033 gemCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304034 if err != nil {
4035 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
4036 return err
4037 }
4038 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
4039 gemStatsInfo.GemId = onuGemStats.GemportId
4040 gemStatsInfo.RxBytes = onuGemStats.RxBytes
4041 gemStatsInfo.RxPackets = onuGemStats.RxPackets
4042 gemStatsInfo.TxBytes = onuGemStats.TxBytes
4043 gemStatsInfo.TxPackets = onuGemStats.TxPackets
4044
4045 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
4046 }
4047 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
4048
4049 default:
4050 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4051 return err
4052 }
4053 } else {
4054 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4055 continue
4056 }
4057 }
4058 }
4059 return err
4060}
4061
4062//nolint:unparam
4063func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4064 singleValResp := extension.SingleGetValueResponse{
4065 Response: &extension.GetValueResponse{
4066 Status: extension.GetValueResponse_OK,
4067 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4068 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4069 },
4070 },
4071 }
4072 errResp := func(status extension.GetValueResponse_Status,
4073 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4074 return &extension.SingleGetValueResponse{
4075 Response: &extension.GetValueResponse{
4076 Status: status,
4077 ErrReason: reason,
4078 },
4079 }
4080 }
4081
4082 var intfID, onuID uint32
4083 if onuDevice != nil {
4084 onuID = onuDevice.ProxyAddress.OnuId
4085 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4086 }
4087
4088 onuKey := dh.formOnuKey(intfID, onuID)
4089 if _, ok := dh.onus.Load(onuKey); !ok {
4090 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4091 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4092 }
4093 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4094
4095 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4096 if err == nil {
4097 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4098 if err != nil {
4099 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4100 }
4101 } else {
4102 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4103 }
4104 return &singleValResp
4105}
4106
nikesh.krishnanc8473432023-06-14 12:14:54 +05304107func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304108 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
bseenivaa1622112025-12-11 18:24:02 +05304109 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4110 OnuInfo, err := dh.Client.GetOnuInfo(subCtx, &Onu)
4111 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304112 if err != nil {
4113 return nil, err
4114 }
4115 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304116}
4117
4118func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304119 Intf := oop.Interface{IntfId: intfID}
bseenivaa1622112025-12-11 18:24:02 +05304120 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4121 IntfInfo, err := dh.Client.GetPonInterfaceInfo(subCtx, &Intf)
4122 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304123 if err != nil {
4124 return nil, err
4125 }
4126 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304127}
4128
Gamze Abaka85e9a142021-05-26 13:41:39 +00004129func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004130 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
bseenivaa1622112025-12-11 18:24:02 +05304131 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4132 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4133 cancel()
Gamze Abaka85e9a142021-05-26 13:41:39 +00004134 if err != nil {
4135 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4136 return generateSingleGetValueErrorResponse(err)
4137 }
4138 return &extension.SingleGetValueResponse{
4139 Response: &extension.GetValueResponse{
4140 Status: extension.GetValueResponse_OK,
4141 Response: &extension.GetValueResponse_RxPower{
4142 RxPower: &extension.GetRxPowerResponse{
4143 IntfId: rxPowerRequest.IntfId,
4144 OnuId: rxPowerRequest.OnuId,
4145 Status: rxPower.Status,
4146 FailReason: rxPower.FailReason.String(),
4147 RxPower: rxPower.RxPowerMeanDbm,
4148 },
4149 },
4150 },
4151 }
4152}
4153
praneeth nalmas55616d62023-02-06 09:19:18 +05304154func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304155 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304156 return &extension.SingleGetValueResponse{
4157 Response: &extension.GetValueResponse{
4158 Status: status,
4159 ErrReason: reason,
4160 },
4161 }
4162 }
4163
4164 resp := extension.SingleGetValueResponse{
4165 Response: &extension.GetValueResponse{
4166 Status: extension.GetValueResponse_OK,
4167 Response: &extension.GetValueResponse_OltRxPower{
4168 OltRxPower: &extension.GetOltRxPowerResponse{},
4169 },
4170 },
4171 }
4172
4173 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4174 portLabel := OltRxPowerRequest.PortLabel
4175 serialNumber := OltRxPowerRequest.OnuSn
4176
4177 portInfo := strings.Split(portLabel, "-")
4178 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4179
4180 if err != nil {
4181 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4182 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4183 }
4184
4185 if portInfo[0] != "pon" {
4186 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4187 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4188 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304189
4190 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304191 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4192 if onuDev != nil {
bseenivaa1622112025-12-11 18:24:02 +05304193 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
praneeth nalmas55616d62023-02-06 09:19:18 +05304194 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
bseenivaa1622112025-12-11 18:24:02 +05304195 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4196 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304197 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304198 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4199 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304200 }
4201
4202 rxPowerValue := extension.RxPower{}
4203 rxPowerValue.OnuSn = onuDev.serialNumber
4204 rxPowerValue.Status = rxPower.GetStatus()
4205 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4206 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4207
4208 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304209 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304210 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4211 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4212 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304213 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304214 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304215 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304216 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
bseenivaa1622112025-12-11 18:24:02 +05304217 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4218 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4219 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304220 if err != nil {
4221 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4222 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304223 rxPowerValue := extension.RxPower{}
4224 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4225 rxPowerValue.Status = rxPower.GetStatus()
4226 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4227 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4228
4229 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4230 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304231 }
4232 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4233 return true
4234 })
4235 }
4236 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4237 return &resp
4238}
4239
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304240func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4241 errResp := func(status extension.GetValueResponse_Status,
4242 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4243 return &extension.SingleGetValueResponse{
4244 Response: &extension.GetValueResponse{
4245 Status: status,
4246 ErrReason: reason,
4247 },
4248 }
4249 }
4250
4251 resp := extension.SingleGetValueResponse{
4252 Response: &extension.GetValueResponse{
4253 Status: extension.GetValueResponse_OK,
4254 Response: &extension.GetValueResponse_OltPonStatsResponse{
4255 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4256 },
4257 },
4258 }
4259
4260 portLabel := ponStatsRequest.GetPortLabel()
4261 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4262
4263 portInfo := strings.Split(portLabel, "-")
4264 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4265
4266 if err != nil {
4267 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4268 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4269 }
4270
4271 if portInfo[0] != "pon" {
4272 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4273 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4274 }
4275
4276 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304277 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4278 ponStats, err := dh.Client.GetPonPortStatistics(subCtx, &Interface)
4279 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304280 if err != nil {
4281 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4282 return generateSingleGetValueErrorResponse(err)
4283 }
4284
4285 ponPortStats := resp.Response.GetOltPonStatsResponse()
4286 ponPortStats.PonPort = uint32(portNumber)
4287 ponPortStats.PortStatistics = ponStats
4288
4289 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4290 return &resp
4291}
4292
4293func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4294 errResp := func(status extension.GetValueResponse_Status,
4295 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4296 return &extension.SingleGetValueResponse{
4297 Response: &extension.GetValueResponse{
4298 Status: status,
4299 ErrReason: reason,
4300 },
4301 }
4302 }
4303
4304 resp := extension.SingleGetValueResponse{
4305 Response: &extension.GetValueResponse{
4306 Status: extension.GetValueResponse_OK,
4307 Response: &extension.GetValueResponse_OltNniStatsResponse{
4308 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4309 },
4310 },
4311 }
4312
4313 portLabel := nniStatsRequest.GetPortLabel()
4314 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4315
4316 portInfo := strings.Split(portLabel, "-")
4317 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4318
4319 if err != nil {
4320 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4321 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4322 }
4323
4324 if portInfo[0] != "nni" {
4325 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4326 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4327 }
4328
4329 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304330 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4331 nniStats, err := dh.Client.GetNniPortStatistics(subCtx, &Interface)
4332 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304333 if err != nil {
4334 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4335 return generateSingleGetValueErrorResponse(err)
4336 }
4337
4338 nniPortStats := resp.Response.GetOltNniStatsResponse()
4339 nniPortStats.NniPort = uint32(portNumber)
4340 nniPortStats.PortStatistics = nniStats
4341
4342 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4343 return &resp
4344}
4345
Akash Kankanala041a2122024-10-16 15:49:22 +05304346// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004347func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304348 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004349 return &extension.SingleGetValueResponse{
4350 Response: &extension.GetValueResponse{
4351 Status: status,
4352 ErrReason: reason,
4353 },
4354 }
4355 }
4356
4357 if err != nil {
4358 if e, ok := status.FromError(err); ok {
4359 switch e.Code() {
4360 case codes.Internal:
4361 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4362 case codes.DeadlineExceeded:
4363 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4364 case codes.Unimplemented:
4365 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4366 case codes.NotFound:
4367 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4368 }
4369 }
4370 }
4371
4372 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4373}
khenaidoo106c61a2021-08-11 18:05:46 -04004374
4375/*
4376Helper functions to communicate with Core
4377*/
4378
4379func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4380 cClient, err := dh.coreClient.GetCoreServiceClient()
4381 if err != nil || cClient == nil {
4382 return nil, err
4383 }
4384 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4385 defer cancel()
4386 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4387}
4388
khenaidoodc2116e2021-10-19 17:33:19 -04004389func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004390 cClient, err := dh.coreClient.GetCoreServiceClient()
4391 if err != nil || cClient == nil {
4392 return nil, err
4393 }
4394 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4395 defer cancel()
4396 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4397}
4398
khenaidoodc2116e2021-10-19 17:33:19 -04004399func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004400 cClient, err := dh.coreClient.GetCoreServiceClient()
4401 if err != nil || cClient == nil {
4402 return err
4403 }
4404 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4405 defer cancel()
4406 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4407 return err
4408}
4409
4410func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4411 cClient, err := dh.coreClient.GetCoreServiceClient()
4412 if err != nil || cClient == nil {
4413 return nil, err
4414 }
4415 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4416 defer cancel()
4417 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4418}
4419
4420func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4421 cClient, err := dh.coreClient.GetCoreServiceClient()
4422 if err != nil || cClient == nil {
4423 return nil, err
4424 }
4425 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4426 defer cancel()
4427 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4428}
4429
4430func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4431 cClient, err := dh.coreClient.GetCoreServiceClient()
4432 if err != nil || cClient == nil {
4433 return err
4434 }
4435 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4436 defer cancel()
4437 _, err = cClient.DeviceUpdate(subCtx, device)
4438 return err
4439}
4440
khenaidoodc2116e2021-10-19 17:33:19 -04004441func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004442 cClient, err := dh.coreClient.GetCoreServiceClient()
4443 if err != nil || cClient == nil {
4444 return nil, err
4445 }
4446 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4447 defer cancel()
4448 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4449}
4450
khenaidoodc2116e2021-10-19 17:33:19 -04004451func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004452 cClient, err := dh.coreClient.GetCoreServiceClient()
4453 if err != nil || cClient == nil {
4454 return err
4455 }
4456 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4457 defer cancel()
4458 _, err = cClient.SendPacketIn(subCtx, pkt)
4459 return err
4460}
4461
4462func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4463 cClient, err := dh.coreClient.GetCoreServiceClient()
4464 if err != nil || cClient == nil {
4465 return err
4466 }
4467 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4468 defer cancel()
4469 _, err = cClient.PortCreated(subCtx, port)
4470 return err
4471}
4472
khenaidoodc2116e2021-10-19 17:33:19 -04004473func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004474 cClient, err := dh.coreClient.GetCoreServiceClient()
4475 if err != nil || cClient == nil {
4476 return err
4477 }
4478 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4479 defer cancel()
4480 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4481 return err
4482}
4483
khenaidoodc2116e2021-10-19 17:33:19 -04004484func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004485 cClient, err := dh.coreClient.GetCoreServiceClient()
4486 if err != nil || cClient == nil {
4487 return err
4488 }
4489 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4490 defer cancel()
4491 _, err = cClient.PortStateUpdate(subCtx, portState)
4492 return err
4493}
4494
khenaidoodc2116e2021-10-19 17:33:19 -04004495func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004496 cClient, err := dh.coreClient.GetCoreServiceClient()
4497 if err != nil || cClient == nil {
4498 return nil, err
4499 }
4500 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4501 defer cancel()
4502 return cClient.GetDevicePort(subCtx, portFilter)
4503}
4504
nikesh.krishnanc8473432023-06-14 12:14:54 +05304505func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4506 cClient, err := dh.coreClient.GetCoreServiceClient()
4507 if err != nil || cClient == nil {
4508 return nil, err
4509 }
4510 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4511 defer cancel()
4512 return cClient.GetPorts(subCtx, portFilter)
4513}
4514
khenaidoo106c61a2021-08-11 18:05:46 -04004515/*
4516Helper functions to communicate with child adapter
4517*/
4518
khenaidoodc2116e2021-10-19 17:33:19 -04004519func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004520 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4521 if err != nil || aClient == nil {
4522 return err
4523 }
4524 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4525 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4526 defer cancel()
4527 _, err = aClient.OmciIndication(subCtx, response)
4528 return err
4529}
4530
khenaidoodc2116e2021-10-19 17:33:19 -04004531func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004532 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4533 if err != nil || aClient == nil {
4534 return err
4535 }
4536 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4537 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4538 defer cancel()
4539 _, err = aClient.OnuIndication(subCtx, onuInd)
4540 return err
4541}
4542
khenaidoodc2116e2021-10-19 17:33:19 -04004543func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004544 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4545 if err != nil || aClient == nil {
4546 return err
4547 }
4548 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4549 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4550 defer cancel()
4551 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4552 return err
4553}
4554
khenaidoodc2116e2021-10-19 17:33:19 -04004555func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004556 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4557 if err != nil || aClient == nil {
4558 return err
4559 }
4560 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4561 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4562 defer cancel()
4563 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4564 return err
4565}
4566
khenaidoodc2116e2021-10-19 17:33:19 -04004567func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004568 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4569 if err != nil || aClient == nil {
4570 return err
4571 }
4572 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4573 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4574 defer cancel()
4575 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4576 return err
4577}
4578
4579/*
4580Helper functions for remote communication
4581*/
4582
4583// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4584// supports is deleted
4585func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4586 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4587
4588 dh.lockChildAdapterClients.Lock()
4589 defer dh.lockChildAdapterClients.Unlock()
4590 if _, ok := dh.childAdapterClients[endpoint]; ok {
4591 // Already set
4592 return nil
4593 }
4594
4595 // Setup child's adapter grpc connection
4596 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004597 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4598 dh.cfg.AdapterEndpoint,
4599 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004600 "onu_inter_adapter_service.OnuInterAdapterService",
4601 dh.onuInterAdapterRestarted,
4602 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004603 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4604 return err
4605 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304606 retryCodes := []codes.Code{
4607 codes.Unavailable, // server is currently unavailable
4608 codes.DeadlineExceeded, // deadline for the operation was exceeded
4609 }
4610 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4611 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 -04004612
nikesh.krishnand9812542023-08-01 18:31:39 +05304613 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004614 // Wait until we have a connection to the child adapter.
4615 // Unlimited retries or until context expires
4616 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4617 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4618 for {
4619 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4620 if err == nil && client != nil {
4621 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4622 break
4623 }
4624 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4625 // Backoff
4626 if err = backoff.Backoff(subCtx); err != nil {
4627 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4628 break
4629 }
4630 }
4631 return nil
4632}
4633
khenaidoodc2116e2021-10-19 17:33:19 -04004634func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004635 // First check from cache
4636 dh.lockChildAdapterClients.RLock()
4637 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4638 dh.lockChildAdapterClients.RUnlock()
4639 return cgClient.GetOnuInterAdapterServiceClient()
4640 }
4641 dh.lockChildAdapterClients.RUnlock()
4642
4643 // Set the child connection - can occur on restarts
4644 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4645 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4646 cancel()
4647 if err != nil {
4648 return nil, err
4649 }
4650
4651 // Get the child client now
4652 dh.lockChildAdapterClients.RLock()
4653 defer dh.lockChildAdapterClients.RUnlock()
4654 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4655 return cgClient.GetOnuInterAdapterServiceClient()
4656 }
4657 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4658}
4659
4660func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4661 dh.lockChildAdapterClients.Lock()
4662 defer dh.lockChildAdapterClients.Unlock()
4663 for key, client := range dh.childAdapterClients {
4664 client.Stop(ctx)
4665 delete(dh.childAdapterClients, key)
4666 }
4667}
4668
khenaidooefff76e2021-12-15 16:51:30 -05004669// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4670func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4671 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004672 return nil
4673}
4674
khenaidooefff76e2021-12-15 16:51:30 -05004675// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4676func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4677 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004678 return nil
4679 }
khenaidooefff76e2021-12-15 16:51:30 -05004680 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004681}
Girish Gowdra950326e2021-11-05 12:43:24 -07004682
4683func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4684 dh.lockDevice.Lock()
4685 defer dh.lockDevice.Unlock()
4686 dh.isDeviceDeletionInProgress = flag
4687}
4688
4689func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4690 dh.lockDevice.RLock()
4691 defer dh.lockDevice.RUnlock()
4692 return dh.isDeviceDeletionInProgress
4693}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004694
4695// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4696// Returns false if waiting timed out.
4697func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4698 c := make(chan struct{})
4699 go func() {
4700 defer close(c)
4701 wg.Wait()
4702 }()
4703 select {
4704 case <-c:
4705 return true // completed normally
4706 case <-time.After(timeout):
4707 return false // timed out
4708 }
4709}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304710
4711func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4712 val, err := json.Marshal(signature)
4713 if err != nil {
4714 logger.Error(ctx, "failed-to-marshal")
4715 return
4716 }
4717 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4718 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4719 }
4720}
4721
4722func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4723 var signature uint32
4724
4725 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4726 if er == nil {
4727 if Value != nil {
4728 Val, er := kvstore.ToByte(Value.Value)
4729 if er != nil {
4730 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4731 return signature
4732 }
4733 if er = json.Unmarshal(Val, &signature); er != nil {
4734 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4735 return signature
4736 }
4737 }
4738 }
4739 return signature
4740}