blob: ee582a6fe4e3596d20b1b866824988f01663a733 [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
bseenivaa20d6c32026-01-11 21:51:19 +05301218 logger.Debugw(ctx, "Dialing 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)
bseenivaa20d6c32026-01-11 21:51:19 +05301266 // decoupling it to avoid blocking state machine transition
1267 go dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001268 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301269}
1270
1271// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301272func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301273 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001274 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001275
1276 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001277 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301278 if err != nil || device == nil {
1279 /*TODO: needs to handle error scenarios */
1280 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1281 }
1282 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001283 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001284
1285 cloned := proto.Clone(device).(*voltha.Device)
1286 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1287 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1288 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001289
khenaidoodc2116e2021-10-19 17:33:19 -04001290 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001291 DeviceId: cloned.Id,
1292 OperStatus: cloned.OperStatus,
1293 ConnStatus: cloned.ConnectStatus,
1294 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301295 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001296 }
1297
bseenivaa1622112025-12-11 18:24:02 +05301298 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Chaitrashree G S44124192019-08-07 20:21:36 -04001299 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
bseenivaa1622112025-12-11 18:24:02 +05301300 _, err = dh.Client.DisableOlt(subCtx, new(oop.Empty))
1301 cancel()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001302 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301303 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001304 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001305 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1306 // all the modules initialized and ready to handle incoming ONUs.
1307
Thomas Lee S985938d2020-05-04 11:40:41 +05301308 err = dh.initializeDeviceHandlerModules(ctx)
1309 if err != nil {
1310 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001311 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001312
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001313 go startHeartbeatCheck(ctx, dh)
1314
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001315 return nil
1316 }
1317
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001318 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301319 logger.Error(ctx, "device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1320 cloned := proto.Clone(device).(*voltha.Device)
1321 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1322 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1323 dh.device = cloned
1324
1325 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
1326 DeviceId: cloned.Id,
1327 OperStatus: cloned.OperStatus,
1328 ConnStatus: cloned.ConnectStatus,
1329 }); err != nil {
1330 logger.Error(ctx, "device-state-update-failed", log.Fields{"device-id": dh.device.Id, "error": err})
1331 }
1332 // decoupling it to avoid blocking state machine transition
1333 go dh.transitionMap.Handle(ctx, GrpcDisconnected)
1334 return nil
Girish Gowdru0c588b22019-04-23 23:24:56 -04001335 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301336
Neha Sharma96b7bf22020-06-15 10:37:32 +00001337 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001338
1339 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001341 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001342
1343 go startHeartbeatCheck(ctx, dh)
1344
cuilin20187b2a8c32019-03-26 19:52:28 -07001345 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301346}
1347
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001348func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001349 var err error
1350 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001351
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001352 if dh.flowMgr != nil {
1353 dh.StopAllFlowRoutines(ctx)
1354 }
1355
1356 dh.CloseKVClient(ctx)
1357
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001358 if err != nil {
1359 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1360 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001361 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1362 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301363 // If collector go routine is active, wait for it to stop
1364 dh.lockDevice.RLock()
1365 if dh.isCollectorActive {
1366 dh.lockDevice.RUnlock()
1367 dh.collectorWaitGroup.Wait()
1368 } else {
1369 dh.lockDevice.RUnlock()
1370 }
yasin saplid0566272021-12-21 09:10:30 +00001371 // +1 is for NNI
1372 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1373 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001374 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001375 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1376 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1377 // There is only one NNI manager since multiple NNI is not supported for now
1378 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001379 // Instantiate resource manager
1380 if dh.resourceMgr[i] = rsrcMgr.NewResourceMgr(ctx, i, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, dh.deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07001381 return olterrors.ErrResourceManagerInstantiating
1382 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001383 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001384 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1385 // the KV store to manage mcast group data. Provide the first instance (0th index)
1386 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1387 return olterrors.ErrGroupManagerInstantiating
1388 }
yasin saplid0566272021-12-21 09:10:30 +00001389 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001390 // Instantiate flow manager
1391 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301392 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001393 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1394 } else {
1395 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001396 }
1397 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001398 /* TODO: Instantiate Alarm , stats , BW managers */
1399 /* Instantiating Event Manager to handle Alarms and KPIs */
1400 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1401
1402 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001403 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001404
1405 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001406}
1407
Neha Sharma96b7bf22020-06-15 10:37:32 +00001408func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001409 var err error
1410 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301411 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001412
bseenivaa1622112025-12-11 18:24:02 +05301413 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1414 deviceInfo, err = dh.Client.GetDeviceInfo(subCtx, new(oop.Empty))
1415 cancel()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001416
1417 if err != nil {
bseenivaa20d6c32026-01-11 21:51:19 +05301418 return nil, olterrors.NewErrCommunication("get-device-info-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001419 }
1420 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001422 }
1423
Neha Sharma96b7bf22020-06-15 10:37:32 +00001424 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001425 dh.device.Root = true
1426 dh.device.Vendor = deviceInfo.Vendor
1427 dh.device.Model = deviceInfo.Model
1428 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1429 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1430 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1431
1432 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001433 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001434 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301435 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001436 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001437 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001438 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001439 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001440 dh.device.MacAddress = genmac
1441 } else {
1442 dh.device.MacAddress = deviceInfo.DeviceId
1443 }
1444
1445 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001446 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001447 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001448 }
1449
1450 return deviceInfo, nil
1451}
1452
Neha Sharma96b7bf22020-06-15 10:37:32 +00001453func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301454 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001455
1456 defer func() {
1457 dh.lockDevice.Lock()
1458 dh.isCollectorActive = false
1459 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301460 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001461 }()
1462
1463 dh.lockDevice.Lock()
1464 dh.isCollectorActive = true
1465 dh.lockDevice.Unlock()
1466
Naga Manjunath7615e552019-10-11 22:35:47 +05301467 for {
1468 select {
1469 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301470 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301471 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001472 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001473
khenaidoo106c61a2021-08-11 18:05:46 -04001474 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001475 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001476 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001477 continue
1478 }
khenaidoo106c61a2021-08-11 18:05:46 -04001479 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301480 // NNI Stats
1481 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001482 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301483 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001485 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001486 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301487 }
1488 // PON Stats
1489 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001490 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301491 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1492 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001493 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001494 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301495 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001496 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001497
yasin sapli9e4c5092022-02-01 13:52:33 +00001498 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001499 if len(onuGemInfoLst) > 0 {
1500 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001501 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001502 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301503 }
1504 }
1505 }
1506}
1507
Mahir Gunyela2e68702022-12-07 00:00:42 -08001508// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301509func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001510 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001511 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301512 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301513
1514 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001515 cgClient, err := dh.coreClient.GetCoreServiceClient()
1516 if err != nil {
1517 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1518 return
1519 }
1520
1521 // Now, set the initial PM configuration for that device
1522 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001523 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301524 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301525}
1526
Mahir Gunyela2e68702022-12-07 00:00:42 -08001527// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001528func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1529 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001530 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301531 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001532 HwDesc: "open_pon",
1533 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001534 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001535 },
1536 SwitchFeatures: &of.OfpSwitchFeatures{
1537 NBuffers: 256,
1538 NTables: 2,
1539 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1540 of.OfpCapabilities_OFPC_TABLE_STATS |
1541 of.OfpCapabilities_OFPC_PORT_STATS |
1542 of.OfpCapabilities_OFPC_GROUP_STATS),
1543 },
1544 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301545}
1546
khenaidoo106c61a2021-08-11 18:05:46 -04001547// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001548func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001549 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001550 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001551 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001552 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001553 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1554 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()
1555 }
khenaidoo106c61a2021-08-11 18:05:46 -04001556 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001557}
1558
Neha Sharma96b7bf22020-06-15 10:37:32 +00001559func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001560 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 -07001561 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 var deviceID string
1563 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001564 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001565
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001566 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001567 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001568 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 -07001569 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1570 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001571
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001572 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301573
1574 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001575 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 -07001576 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001577
khenaidoodc2116e2021-10-19 17:33:19 -04001578 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001579 ParentId: dh.device.Id,
1580 OnuId: omciInd.OnuId,
1581 ParentPortNo: ponPort,
1582 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001583 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301584 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001585 "intf-id": omciInd.IntfId,
1586 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001587 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001588 deviceType = onuDevice.Type
1589 deviceID = onuDevice.Id
1590 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001591 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301592 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001593 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001594 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301595 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 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 +05301597 deviceType = onuInCache.(*OnuDevice).deviceType
1598 deviceID = onuInCache.(*OnuDevice).deviceID
1599 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001600 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001601 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001602
khenaidoodc2116e2021-10-19 17:33:19 -04001603 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001604 ParentDeviceId: proxyDeviceID,
1605 ChildDeviceId: deviceID,
1606 Message: omciInd.Pkt,
1607 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301608 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001609 "source": dh.openOLT.config.AdapterEndpoint,
1610 "device-type": deviceType,
1611 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001612 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001613 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001614 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001615 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301616}
1617
khenaidoo106c61a2021-08-11 18:05:46 -04001618// //ProcessInterAdapterMessage sends the proxied messages to the target device
1619// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1620// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001621// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001622// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001623// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001624// return dh.handleInterAdapterOmciMsg(ctx, msg)
1625// }
1626// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1627// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001628
kesavandb9f54fd2021-11-25 20:08:04 +05301629// ProxyOmciRequests sends the proxied OMCI message to the target device
1630func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301631 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1632 return status.Error(codes.Unavailable, "OLT unreachable")
1633 }
kesavandb9f54fd2021-11-25 20:08:04 +05301634 if omciMsgs.GetProxyAddress() == nil {
1635 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1636 if err != nil {
1637 return olterrors.NewErrNotFound("onu", log.Fields{
1638 "parent-device-id": dh.device.Id,
1639 "child-device-id": omciMsgs.ChildDeviceId}, err)
1640 }
1641 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1642 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1643 return olterrors.NewErrCommunication("send-failed", log.Fields{
1644 "parent-device-id": dh.device.Id,
1645 "child-device-id": omciMsgs.ChildDeviceId}, err)
1646 }
1647 } else {
1648 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1649 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1650 return olterrors.NewErrCommunication("send-failed", log.Fields{
1651 "parent-device-id": dh.device.Id,
1652 "child-device-id": omciMsgs.ChildDeviceId}, err)
1653 }
1654 }
1655 return nil
1656}
1657
1658func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1659 var intfID uint32
1660 var onuID uint32
1661 var connectStatus common.ConnectStatus_Types
1662 if onuDevice != nil {
1663 intfID = onuDevice.ProxyAddress.GetChannelId()
1664 onuID = onuDevice.ProxyAddress.GetOnuId()
1665 connectStatus = onuDevice.ConnectStatus
1666 } else {
1667 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1668 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1669 connectStatus = omciMsgs.GetConnectStatus()
1670 }
1671 if connectStatus != voltha.ConnectStatus_REACHABLE {
1672 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1673
1674 return olterrors.NewErrCommunication("unreachable", log.Fields{
1675 "intf-id": intfID,
1676 "onu-id": onuID}, nil)
1677 }
1678
1679 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1680 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1681
1682 onuSecOmciMsgList := omciMsgs.GetMessages()
1683
1684 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301685 var omciMessage *oop.OmciMsg
1686 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1687 hex.Encode(hexPkt, onuSecOmciMsg)
1688 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1689
1690 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1691 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1692 //https://jira.opencord.org/browse/VOL-4604
1693 transid := extractOmciTransactionID(onuSecOmciMsg)
1694 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1695 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1696
bseenivaa1622112025-12-11 18:24:02 +05301697 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1698 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1699 cancel()
kesavandb9f54fd2021-11-25 20:08:04 +05301700 if err != nil {
1701 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1702 "intf-id": intfID,
1703 "onu-id": onuID,
1704 "message": omciMessage}, err)
1705 }
1706 }
1707 return nil
1708}
1709
khenaidoo106c61a2021-08-11 18:05:46 -04001710// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001711func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001712 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 -07001713
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301714 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1715 return status.Error(codes.Unavailable, "OLT unreachable")
1716 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001717 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001718 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001719 if err != nil {
1720 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001721 "parent-device-id": dh.device.Id,
1722 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001723 }
khenaidoo106c61a2021-08-11 18:05:46 -04001724 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1725 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001726 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001727 "parent-device-id": dh.device.Id,
1728 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001729 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001730 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001731 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1732 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001733 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001734 "parent-device-id": dh.device.Id,
1735 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001736 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001737 }
1738 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301739}
1740
khenaidoodc2116e2021-10-19 17:33:19 -04001741func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001742 var intfID uint32
1743 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001744 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001745 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001746 intfID = onuDevice.ProxyAddress.GetChannelId()
1747 onuID = onuDevice.ProxyAddress.GetOnuId()
1748 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001749 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001750 intfID = omciMsg.GetProxyAddress().GetChannelId()
1751 onuID = omciMsg.GetProxyAddress().GetOnuId()
1752 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001753 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001754 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755 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 -08001756
Thomas Lee S94109f12020-03-03 16:39:29 +05301757 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001758 "intf-id": intfID,
1759 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001760 }
1761
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001762 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1763 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301764 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001765 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001766 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1767 hex.Encode(hexPkt, omciMsg.Message)
1768 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1769
1770 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1771 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1772 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001773 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001774 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001775
bseenivaa1622112025-12-11 18:24:02 +05301776 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1777 _, err := dh.Client.OmciMsgOut(subCtx, omciMessage)
1778 cancel()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001779 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301780 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001781 "intf-id": intfID,
1782 "onu-id": onuID,
1783 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001784 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001785 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001786}
1787
David K. Bainbridge794735f2020-02-11 21:01:37 -08001788func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301789 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 +00001790 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001791 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001792 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001793 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301794 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
bseenivaa1622112025-12-11 18:24:02 +05301795 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1796 defer cancel()
1797 if _, err := dh.Client.ActivateOnu(subCtx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001798 st, _ := status.FromError(err)
1799 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001800 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 -04001801 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301802 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001803 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001804 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001805 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001806 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001807 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001808}
1809
Mahir Gunyela2e68702022-12-07 00:00:42 -08001810// getChildDevice function can be used in general to get child device, if not found in cache the function will
1811// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301812func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1813 var InCacheOnuDev *OnuDevice
1814 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1815 if onuInCache.(*OnuDevice).serialNumber == sn {
1816 InCacheOnuDev = onuInCache.(*OnuDevice)
1817 return false
1818 }
1819 return true
1820 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301821 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301822 if InCacheOnuDev != nil {
1823 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1824 return InCacheOnuDev
1825 }
1826 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1827 ParentId: dh.device.Id,
1828 SerialNumber: sn,
1829 ParentPortNo: parentPortNo,
1830 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301831 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301832 if onuDevice == nil {
1833 return nil
1834 }
1835 onuID := onuDevice.ProxyAddress.OnuId
1836 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1837 onuKey := dh.formOnuKey(intfID, onuID)
1838
1839 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1840 dh.onus.Store(onuKey, onuDev)
1841 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1842 return onuDev
1843}
1844
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301845// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1846// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301847func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001848 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301849 // 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 +05301850 // 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 +05301851 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1852 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1853 ParentId: dh.device.Id,
1854 SerialNumber: sn,
1855 ParentPortNo: parentPortNo,
1856 })
1857 if onuDevice != nil {
1858 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1859 return true, nil
1860 }
1861 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1862
1863 return false, nil
1864 } else {
1865 tpInstExists := false
1866 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301867 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1868 if onuDev != nil {
1869 var onuGemInfo *rsrcMgr.OnuGemInfo
1870 var err error
1871 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1872 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1873 return false, err
1874 }
1875 if onuGemInfo != nil {
1876 for _, uni := range onuGemInfo.UniPorts {
1877 uniID := plt.UniIDFromPortNum(uni)
1878 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1879 if len(tpIDs) != 0 {
1880 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1881 tpInstExists = true
1882 break
1883 }
1884 }
1885 }
1886 }
1887 return tpInstExists, nil
1888 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301889}
1890
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001891// processDiscONULOSClear clears the LOS Alarm if it's needed
1892func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301893 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001894 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301895
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001896 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1897 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1898 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1899 OnuLosRaise event sent for it */
1900 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1901 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1902 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1903 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1904 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1905 "currentIntfId": onuDiscInd.GetIntfId()})
1906 // TODO:: Should we need to ignore raising OnuLosClear event
1907 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301908 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001909 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1910 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1911 alarmInd.LosStatus = statusCheckOff
1912 go func() {
1913 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1914 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1915 }
1916 }()
1917 // stop iterating
1918 return false
1919 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301920 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001921 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301922}
1923
bseeniva43b5a912025-06-05 12:48:15 +05301924func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1925 if err != nil || tpInstExists {
1926 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1927 } else {
1928 // once the function completes set the value to false so that
1929 // we know the processing has inProcess.
1930 // Note that this is done after checking if we are already processing
1931 // to avoid changing the value from a different thread
1932 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1933 dh.discOnus.Store(sn, false)
1934 }
1935}
1936
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301937func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301938 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301939 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301940
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301941 channelID := onuDiscInd.GetIntfId()
1942 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1943
1944 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301945 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301946 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301947 }()
1948
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301949 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1950
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301951 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1952 if !dh.cfg.ForceOnuDiscIndProcessing {
1953 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1954 if error != nil {
1955 return error
1956 }
1957 if tpInstExists {
1958 // ignore the discovery if tpinstance is present.
1959 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1960 return nil
1961 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001962 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001963 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1964
1965 // if the ONU existed, handle the LOS Alarm
1966 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001967 if inProcess.(bool) {
1968 // if we're currently processing the ONU on a different thread, do nothing
1969 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1970 return nil
1971 }
1972 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1973 // then continue processing it
1974 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1975
1976 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001977 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301978 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001979 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001980
1981 // check the ONU is already know to the OLT
1982 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301983 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001984 ParentId: dh.device.Id,
1985 SerialNumber: sn,
1986 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001987
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301988 if error != nil {
1989 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1990 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001991 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 -08001992 switch e.Code() {
1993 case codes.Internal:
1994 // this probably means NOT FOUND, so just create a new device
1995 onuDevice = nil
1996 case codes.DeadlineExceeded:
1997 // if the call times out, cleanup and exit
1998 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301999 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
2000 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002001 }
2002 }
2003 }
2004
2005 if onuDevice == nil {
2006 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00002007 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002008 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04002009 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302010 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002011 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08002012
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302013 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002014 // if we can't create an ID in resource manager,
2015 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08002016 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302017
2018 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002019 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302020 "serial-number": sn}, error)
2021 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002022 }
2023
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302024 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04002025 ParentId: dh.device.Id,
2026 ParentPortNo: parentPortNo,
2027 ChannelId: channelID,
2028 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
2029 SerialNumber: sn,
2030 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302031 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002032 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00002033 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 +05302034
2035 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002036 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302037 "serial-number": sn}, error)
2038 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002039 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302040 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 +05302041 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2042 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2043 "onu-id": onuID,
2044 "device-id": dh.device.Id,
2045 "serial-number": sn}, error)
2046 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002047 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002048 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302049 log.Fields{"onuDevice": onuDevice,
2050 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002051 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302052 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002053 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002054
khenaidoo106c61a2021-08-11 18:05:46 -04002055 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2056 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302057 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002058 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302059 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302060 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2061 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002062 }
2063
Matteo Scandolo945e4012019-12-12 14:16:11 -08002064 // we can now use the existing ONU Id
2065 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302066 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002067 //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 +00002068 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002069 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302070 "intfId": onuDiscInd.GetIntfId(),
2071 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002072 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002073
khenaidoo106c61a2021-08-11 18:05:46 -04002074 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302075 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002076 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302077 log.Fields{"onu": onuDev,
2078 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002079
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302080 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002081 DeviceId: onuDevice.Id,
2082 ParentDeviceId: dh.device.Id,
2083 OperStatus: common.OperStatus_DISCOVERED,
2084 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302085 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302086 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302088 "serial-number": sn}, error)
2089 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002090 }
khenaidoo106c61a2021-08-11 18:05:46 -04002091
Neha Sharma96b7bf22020-06-15 10:37:32 +00002092 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302093 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302094 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002095 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302096 "serial-number": sn}, error)
2097 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002098 }
2099 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002100}
2101
Mahir Gunyelb0046752021-02-26 13:51:05 -08002102func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002103 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002104 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002105 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002106 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002107 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302108 log.Fields{"onuId": onuInd.OnuId,
2109 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302110 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002111 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002112 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002113 errFields := log.Fields{"device-id": dh.device.Id}
2114
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302115 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302116 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002117 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002118 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002119 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002120 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302121 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002122 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002123 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002124 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002125 errFields["onu-id"] = onuInd.OnuId
2126 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002127 }
khenaidoodc2116e2021-10-19 17:33:19 -04002128 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002129 ParentId: dh.device.Id,
2130 SerialNumber: serialNumber,
2131 OnuId: onuInd.OnuId,
2132 ParentPortNo: ponPort,
2133 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002134 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002135
David K. Bainbridge794735f2020-02-11 21:01:37 -08002136 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002137 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002138 }
2139
David K. Bainbridge794735f2020-02-11 21:01:37 -08002140 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002142 "previousIntfId": onuDevice.ParentPortNo,
2143 "currentIntfId": ponPort})
2144 }
2145
2146 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002147 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302148 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2149 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302150 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002151 }
2152 if !foundInCache {
2153 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002154 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 -08002155 }
kesavand7cf3a052020-08-28 12:49:18 +05302156 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002157 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002158 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302159 }
2160 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002161 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002162 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002163 }
2164 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002165}
2166
Neha Sharma96b7bf22020-06-15 10:37:32 +00002167func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 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 -07002169 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2170 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2171 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2172 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002173 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002174 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2175 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002176 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002177 onuInd.OperState = "down"
2178 }
2179 }
2180
David K. Bainbridge794735f2020-02-11 21:01:37 -08002181 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002182 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002183 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 -04002184
khenaidoodc2116e2021-10-19 17:33:19 -04002185 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002186 DeviceId: onuDevice.Id,
2187 OnuIndication: onuInd,
2188 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002189 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302190 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002191 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002192 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002193 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002194 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002195 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002196 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002197 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002198 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002199 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002200}
2201
cuilin20187b2a8c32019-03-26 19:52:28 -07002202func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2203 if serialNum != nil {
2204 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002205 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002206 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002207}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002208func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2209 decodedStr, err := hex.DecodeString(serialNum[4:])
2210 if err != nil {
2211 return nil, err
2212 }
2213 return &oop.SerialNumber{
2214 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002215 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002216 }, nil
2217}
cuilin20187b2a8c32019-03-26 19:52:28 -07002218
2219func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002220 if len(vendorSpecific) > 3 {
2221 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2222 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2223 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2224 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2225 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2226 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2227 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2228 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2229 return tmp
2230 }
2231 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002232}
2233
Mahir Gunyela2e68702022-12-07 00:00:42 -08002234// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002235func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302236 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002237}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002238
Mahir Gunyela2e68702022-12-07 00:00:42 -08002239// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2241 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302242 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002243 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302244 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002245
khenaidoodc2116e2021-10-19 17:33:19 -04002246 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002247 ParentId: dh.device.Id,
2248 OnuId: onuID,
2249 ParentPortNo: parentPort,
2250 })
2251
Girish Gowdru0c588b22019-04-23 23:24:56 -04002252 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002253 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002254 "intf-id": parentPort,
2255 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002256 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002257 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 -08002258 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302259}
2260
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002261// SendPacketInToCore sends packet-in to core
2262// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2263// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002265 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002266 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002267 "port": logicalPort,
2268 "packet": hex.EncodeToString(packetPayload),
2269 "device-id": dh.device.Id,
2270 })
2271 }
khenaidoo106c61a2021-08-11 18:05:46 -04002272
khenaidoodc2116e2021-10-19 17:33:19 -04002273 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002274 DeviceId: dh.device.Id,
2275 Port: logicalPort,
2276 Packet: packetPayload,
2277 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302278 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002279 "source": "adapter",
2280 "destination": "core",
2281 "device-id": dh.device.Id,
2282 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002283 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002284 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002285 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002286 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002287 "packet": hex.EncodeToString(packetPayload),
2288 "device-id": dh.device.Id,
2289 })
2290 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002291 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002292}
2293
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002294// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002295func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002297
2298 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2299 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002300 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002301 }
2302
Kent Hagermane6ff1012020-07-14 15:07:53 -04002303 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002304 metrics := dh.metrics.GetSubscriberMetrics()
2305 for _, m := range pmConfigs.Metrics {
2306 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002307 }
2308 }
2309}
2310
khenaidoodc2116e2021-10-19 17:33:19 -04002311func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002312 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002313 var errorsList []error
2314
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002315 if dh.getDeviceDeletionInProgressFlag() {
2316 // The device itself is going to be reset as part of deletion. So nothing to be done.
2317 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2318 return nil
2319 }
2320
Girish Gowdru0c588b22019-04-23 23:24:56 -04002321 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002322 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302323 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002324
Neha Sharma96b7bf22020-06-15 10:37:32 +00002325 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302326 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002327 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302328 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002329 if flow_utils.HasGroup(flow) {
2330 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2331 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002332 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2333 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2334 } else {
2335 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2336 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002337 }
Girish Gowdracefae192020-03-19 18:14:10 -07002338 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002339 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302340 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002341 logger.Warnw(ctx, "flow-to-remove-not-found",
2342 log.Fields{
2343 "ponIf": intfID,
2344 "flowToRemove": flow,
2345 "error": err,
2346 })
2347 } else {
2348 errorsList = append(errorsList, err)
2349 }
Girish Gowdracefae192020-03-19 18:14:10 -07002350 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002351 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302352
2353 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302354 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002355 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302356 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002357 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302358 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002359 if flow_utils.HasGroup(flow) {
2360 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2361 } else {
yasin saplid0566272021-12-21 09:10:30 +00002362 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002363 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2364 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2365 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2366 } else {
yasin saplid0566272021-12-21 09:10:30 +00002367 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002368 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002369 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002370 if err != nil {
2371 errorsList = append(errorsList, err)
2372 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302373 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002374 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002375
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002376 return errorsList
2377}
2378
2379func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2380 var err error
2381 var errorsList []error
2382
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002383 if dh.getDeviceDeletionInProgressFlag() {
2384 // The device itself is going to be reset as part of deletion. So nothing to be done.
2385 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2386 return nil
2387 }
2388
Girish Gowdracefae192020-03-19 18:14:10 -07002389 // 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 +00002390 if groups != nil {
2391 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002392 // err = dh.groupMgr.AddGroup(ctx, group)
2393 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002394 if err != nil {
2395 errorsList = append(errorsList, err)
2396 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002397 }
2398 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002399 // err = dh.groupMgr.ModifyGroup(ctx, group)
2400 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002401 if err != nil {
2402 errorsList = append(errorsList, err)
2403 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002404 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002405 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002406 // err = dh.groupMgr.DeleteGroup(ctx, group)
2407 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002408 if err != nil {
2409 errorsList = append(errorsList, err)
2410 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002411 }
2412 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002413
2414 return errorsList
2415}
2416
Mahir Gunyela2e68702022-12-07 00:00:42 -08002417// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002418func (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 -07002419 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002420
2421 if dh.getDeviceDeletionInProgressFlag() {
2422 // The device itself is going to be reset as part of deletion. So nothing to be done.
2423 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2424 return nil
2425 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302426 if dh.transitionMap.currentDeviceState != deviceStateUp {
2427 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2428 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2429 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002430 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2431 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2432 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002433 if len(errorsList) > 0 {
2434 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2435 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002437 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302438}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002439
Mahir Gunyela2e68702022-12-07 00:00:42 -08002440// DisableDevice disables the given device
2441// It marks the following for the given device:
2442// Device-Handler Admin-State : down
2443// Device Port-State: UNKNOWN
2444// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002445func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002446 /* On device disable ,admin state update has to be done prior sending request to agent since
2447 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002448 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302449 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2450 if _, err := dh.Client.DisableOlt(subCtx, new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002451 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302452 cancel()
Girish Kumarf26e4882020-03-05 06:49:10 +00002453 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002454 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002455 }
bseenivaa1622112025-12-11 18:24:02 +05302456 cancel()
Chaitrashree G S44124192019-08-07 20:21:36 -04002457 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002459 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002460 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302461
2462 dh.discOnus = sync.Map{}
2463 dh.onus = sync.Map{}
2464
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002465 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302466 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002467 if dh.isCollectorActive {
2468 dh.stopCollector <- true
2469 }
2470 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302471
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002473 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302474 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302475 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002476
kdarapu1afeceb2020-02-12 01:38:09 -05002477 // 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 -04002478 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002479 DeviceId: cloned.Id,
2480 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2481 OperStatus: voltha.OperStatus_UNKNOWN,
2482 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002483 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002484 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002485 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002486 return nil
2487}
2488
Neha Sharma96b7bf22020-06-15 10:37:32 +00002489func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002490 // Update onu state as unreachable in onu adapter
2491 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302492 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002493
Akash Kankanala041a2122024-10-16 15:49:22 +05302494 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002495 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002496 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002497 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 -04002498 }
2499 if onuDevices != nil {
2500 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002501 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002502 DeviceId: onuDevice.Id,
2503 OnuIndication: &onuInd,
2504 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002505 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002506 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002507 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002508 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002509 }
2510 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002511}
2512
Mahir Gunyela2e68702022-12-07 00:00:42 -08002513// ReenableDevice re-enables the olt device after disable
2514// It marks the following for the given device:
2515// Device-Handler Admin-State : up
2516// Device Port-State: ACTIVE
2517// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002518func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302519 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302520 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2521 if _, err := dh.Client.ReenableOlt(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302522 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
bseenivaa1622112025-12-11 18:24:02 +05302523 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302524 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2525 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302526 }
bseenivaa1622112025-12-11 18:24:02 +05302527 cancel()
nikesh.krishnane363ace2023-02-28 03:12:38 +05302528 } else {
2529 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 +05302530 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002531 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002532
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002533 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002534 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002535 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002536 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002537 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2538 } else {
2539 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2540 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2541 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002542 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002543 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302544 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002545 device.OperStatus = voltha.OperStatus_ACTIVE
2546 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302547 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002548 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002549 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002550 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002551
khenaidoodc2116e2021-10-19 17:33:19 -04002552 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002553 DeviceId: device.Id,
2554 OperStatus: device.OperStatus,
2555 ConnStatus: device.ConnectStatus,
2556 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302557 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002558 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002559 "connect-status": device.ConnectStatus,
2560 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002561 }
kesavand39e0aa32020-01-28 20:58:50 -05002562
Neha Sharma96b7bf22020-06-15 10:37:32 +00002563 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002564
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002565 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002566}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002567
npujarec5762e2020-01-01 14:08:48 +05302568func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002569 var uniID uint32
2570 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002571 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302572 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002573 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002574 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002575 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002576 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2577 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2578 } else {
2579 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2580 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002581 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002582 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002583 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002584 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002585 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002586 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002587 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002588 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002589 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002590 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002591 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002592 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002593 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002594 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002595 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002596 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302597 }
yasin saplibddc2d72022-02-08 13:10:17 +00002598 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2599 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002600 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002601 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302602 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002603 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002604 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002605 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 -03002606 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002607 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002608 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002609 if len(errs) > 0 {
2610 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2611 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2612 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002613 return nil
2614}
2615
Devmalya Paul495b94a2019-08-27 19:42:00 -04002616// 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 +05302617func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002618 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002619 /* Clear the KV store data associated with the all the UNI ports
2620 This clears up flow data and also resource map data for various
2621 other pon resources like alloc_id and gemport_id
2622 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002623
Abhay Kumarb87ac882025-10-30 09:55:07 +00002624 if dh.getDeviceDeletionInProgressFlag() {
2625 logger.Errorw(ctx, "cannot complete operation as device deletion is in progress", log.Fields{"device-id": dh.device.Id})
2626 return olterrors.NewErrAdapter(fmt.Errorf("cannot complete operation as device deletion is in progress").Error(), log.Fields{"device-id": dh.device.Id}, nil)
2627 }
2628
Girish Gowdra950326e2021-11-05 12:43:24 -07002629 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002630 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002631
Himani Chawla49a5d562020-11-25 11:53:44 +05302632 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002633 // Stop the Stats collector
2634 if dh.isCollectorActive {
2635 dh.stopCollector <- true
2636 }
2637 // stop the heartbeat check routine
2638 if dh.isHeartbeatCheckActive {
2639 dh.stopHeartbeatCheck <- true
2640 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302641 // Stop the read indication only if it the routine is active
2642 if dh.isReadIndicationRoutineActive {
2643 dh.stopIndications <- true
2644 }
2645 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302646
2647 err := dh.cleanupDeviceResources(ctx)
2648 if err != nil {
2649 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2650 } else {
2651 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2652 }
2653
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002654 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302655 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002656 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302657 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2658 if _, err = dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002659 go func() {
2660 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302661 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2662 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002663 }
2664 }()
2665 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002666 }
bseenivaa1622112025-12-11 18:24:02 +05302667 cancel()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002668 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002669 // There is no need to update the core about operation status and connection status of the OLT.
2670 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2671 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2672 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002673
khenaidoo7eb2d672021-10-22 19:08:50 -04002674 // Stop the adapter grpc clients for that parent device
2675 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002676 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002677}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002678
2679// StopAllFlowRoutines stops all flow routines
2680func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2681 var wg sync.WaitGroup
2682 wg.Add(1) // for the mcast routine below to finish
2683 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2684 for _, flMgr := range dh.flowMgr {
2685 if flMgr != nil {
2686 wg.Add(1) // for the flow handler routine below to finish
2687 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2688 }
2689 }
2690 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2691 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2692 } else {
2693 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2694 }
2695}
2696
Gustavo Silva41af9122022-10-11 11:05:13 -03002697func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2698 var errs []error
Abhay Kumarb87ac882025-10-30 09:55:07 +00002699 if dh.resourceMgr != nil && dh.totalPonPorts > 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302700 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002701 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002702 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002703 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002704 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002705 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2706 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302707 }
2708 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002709 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2710 errs = append(errs, err)
2711 }
2712 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2713 errs = append(errs, err)
2714 }
2715 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2716 errs = append(errs, err)
2717 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002718 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002719 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002720 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002721 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002722 }
2723 // Clean up NNI manager's data
2724 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2725 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002726 }
A R Karthick1f85b802019-10-11 05:06:05 +00002727
Abhay Kumarb87ac882025-10-30 09:55:07 +00002728 logger.Debugw(ctx, "lockDevice for KVStore close client", log.Fields{"deviceID": dh.device.Id})
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002729 dh.CloseKVClient(ctx)
2730
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002731 // Take one final sweep at cleaning up KV store for the OLT device
2732 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002733 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2734 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002735 }
2736
Devmalya Paul495b94a2019-08-27 19:42:00 -04002737 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302738 dh.onus.Range(func(key interface{}, value interface{}) bool {
2739 dh.onus.Delete(key)
2740 return true
2741 })
2742
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002743 /*Delete discovered ONU map for the device*/
2744 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2745 dh.discOnus.Delete(key)
2746 return true
2747 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002748 if len(errs) > 0 {
2749 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2750 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2751 }
2752 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002753}
2754
Mahir Gunyela2e68702022-12-07 00:00:42 -08002755// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002756func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302757 if dh.Client != nil {
bseenivaa1622112025-12-11 18:24:02 +05302758 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2759 defer cancel()
2760 if _, err := dh.Client.Reboot(subCtx, new(oop.Empty)); err != nil {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302761 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2762 }
2763 } else {
2764 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 -04002765 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302766
Neha Sharma96b7bf22020-06-15 10:37:32 +00002767 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002768 return nil
2769}
2770
David K. Bainbridge794735f2020-02-11 21:01:37 -08002771func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002772 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002773 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002774 "packet-indication": *packetIn,
2775 "device-id": dh.device.Id,
2776 "packet": hex.EncodeToString(packetIn.Pkt),
2777 })
2778 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002779 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2780 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2781 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002782 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002783 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002784 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002785 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002786 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002787 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002788 "logical-port-num": logicalPortNum,
2789 "device-id": dh.device.Id,
2790 "packet": hex.EncodeToString(packetIn.Pkt),
2791 })
2792 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002793
khenaidoodc2116e2021-10-19 17:33:19 -04002794 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002795 DeviceId: dh.device.Id,
2796 Port: logicalPortNum,
2797 Packet: packetIn.Pkt,
2798 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302799 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002800 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302801 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002802 "device-id": dh.device.Id,
2803 "packet": hex.EncodeToString(packetIn.Pkt),
2804 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002805 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002806
Matteo Scandolo92186242020-06-12 10:54:18 -07002807 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002808 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002809 "packet": hex.EncodeToString(packetIn.Pkt),
2810 "device-id": dh.device.Id,
2811 })
2812 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002813 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002814}
2815
Mahir Gunyela2e68702022-12-07 00:00:42 -08002816// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2817func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2818 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2819 if err != nil {
2820 return olterrors.NewErrInvalidValue(log.Fields{
2821 "egress-nni-port": egressPortNo,
2822 "device-id": dh.device.Id,
2823 }, err)
2824 }
2825 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2826
2827 if logger.V(log.DebugLevel) {
2828 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2829 "uplink-pkt": uplinkPkt,
2830 "packet": hex.EncodeToString(packet.Data),
2831 "device-id": dh.device.Id,
2832 })
2833 }
2834
bseenivaa1622112025-12-11 18:24:02 +05302835 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2836 defer cancel()
2837 if _, err := dh.Client.UplinkPacketOut(subCtx, &uplinkPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002838 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2839 "packet": hex.EncodeToString(packet.Data),
2840 "device-id": dh.device.Id,
2841 }, err)
2842 }
2843 return nil
2844}
2845
2846// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2847func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2848 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2849 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2850 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2851 // Do not packet-out lldp packets on uni port.
2852 // ONOS has no clue about uni/nni ports, it just packets out on all
2853 // available ports on the Logical Switch. It should not be interested
2854 // in the UNI links.
2855 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2856 "device-id": dh.device.Id,
2857 })
2858 return nil
2859 }
2860 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2861 if innerEthType == 0x8100 {
2862 // q-in-q 802.1ad or 802.1q double tagged packet.
2863 // slice out the outer tag.
2864 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2865 if logger.V(log.DebugLevel) {
2866 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2867 "packet-data": hex.EncodeToString(packet.Data),
2868 "device-id": dh.device.Id,
2869 })
2870 }
2871 }
2872 }
2873 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2874 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2875 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2876 var gemPortID uint32
2877 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2878 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2879 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2880 }
2881 if err != nil {
2882 // In this case the openolt agent will receive the gemPortID as 0.
2883 // The agent tries to retrieve the gemPortID in this case.
2884 // This may not always succeed at the agent and packetOut may fail.
2885 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2886 "intf-id": intfID,
2887 "onu-id": onuID,
2888 "uni-id": uniID,
2889 "packet": hex.EncodeToString(packet.Data),
2890 "device-id": dh.device.Id,
2891 "error": err,
2892 })
2893 }
2894
2895 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2896 if logger.V(log.DebugLevel) {
2897 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2898 "egress-port-no": egressPortNo,
2899 "intf-id": intfID,
2900 "onu-id": onuID,
2901 "uni-id": uniID,
2902 "gem-port-id": gemPortID,
2903 "packet": hex.EncodeToString(packet.Data),
2904 "device-id": dh.device.Id,
2905 })
2906 }
2907
bseenivaa1622112025-12-11 18:24:02 +05302908 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2909 defer cancel()
2910 if _, err := dh.Client.OnuPacketOut(subCtx, &onuPkt); err != nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002911 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2912 "source": "adapter",
2913 "destination": "onu",
2914 "egress-port-number": egressPortNo,
2915 "intf-id": intfID,
2916 "oni-id": onuID,
2917 "uni-id": uniID,
2918 "gem-port-id": gemPortID,
2919 "packet": hex.EncodeToString(packet.Data),
2920 "device-id": dh.device.Id,
2921 }, err)
2922 }
2923 return nil
2924}
2925
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002926// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002927func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002928 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002929 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002930 "device-id": dh.device.Id,
2931 "egress-port-no": egressPortNo,
2932 "pkt-length": len(packet.Data),
2933 "packet": hex.EncodeToString(packet.Data),
2934 })
2935 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002936
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002937 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002938 var err error
mgouda86543582025-10-29 20:58:16 +05302939 switch egressPortType {
2940 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002941 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302942 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002943 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302944 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002945 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302946 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002947 "egressPortType": egressPortType,
2948 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302949 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002950 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002951 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002952 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002953}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002954
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002955func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2956 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002957}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302958
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002959func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002960 defer func() {
2961 dh.lockDevice.Lock()
2962 dh.isHeartbeatCheckActive = false
2963 dh.lockDevice.Unlock()
2964 }()
2965
2966 dh.lockDevice.Lock()
2967 dh.isHeartbeatCheckActive = true
2968 dh.lockDevice.Unlock()
2969
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302970 // start the heartbeat check towards the OLT.
2971 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302972 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302973
2974 for {
2975 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2976 select {
2977 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002978 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002979 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002980 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302981 if timerCheck == nil {
2982 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002983 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302984 }
2985 } else {
2986 if timerCheck != nil {
2987 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002988 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302989 }
2990 timerCheck = nil
2991 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302992 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2993 if dh.heartbeatSignature == 0 {
2994 // First time the signature will be 0, update the signture to DB when not found.
2995 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2996 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2997 }
2998 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2999
3000 dh.lockDevice.RLock()
3001 // Stop the read indication only if it the routine is active
3002 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3003 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3004 // on next execution of the readIndication routine.
3005 if !dh.isReadIndicationRoutineActive {
3006 // Start reading indications
3007 go func() {
3008 if err = dh.readIndications(ctx); err != nil {
3009 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3010 }
3011 }()
3012 }
3013 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303014 } else {
3015 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
3016 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
3017 dh.heartbeatSignature = heartBeat.HeartbeatSignature
3018 go dh.updateStateRebooted(ctx)
3019 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303020 }
3021 cancel()
3022 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003023 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303024 return
3025 }
3026 }
3027}
3028
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003029func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04003030 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003031 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07003032 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3033 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3034 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3035 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3036 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003037 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07003038 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3039 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003040 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303041
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303042 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003043 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003044 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04003045 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04003046 DeviceId: dh.device.Id,
3047 OperStatus: voltha.OperStatus_UNKNOWN,
3048 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
3049 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003050 _ = 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 -04003051 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303052 /*
3053 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
3054 DeviceId: dh.device.Id,
3055 PortTypeFilter: 0,
3056 OperStatus: voltha.OperStatus_UNKNOWN,
3057 }); err != nil {
3058 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3059 }
3060 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003061
Akash Kankanala041a2122024-10-16 15:49:22 +05303062 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003063 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003064 cloned := proto.Clone(device).(*voltha.Device)
3065 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3066 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3067 dh.device = cloned // update local copy of the device
3068 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003069
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003070 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003071 // Stop the Stats collector
3072 if dh.isCollectorActive {
3073 dh.stopCollector <- true
3074 }
3075 // stop the heartbeat check routine
3076 if dh.isHeartbeatCheckActive {
3077 dh.stopHeartbeatCheck <- true
3078 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003079 // Stop the read indication only if it the routine is active
3080 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3081 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3082 // on next execution of the readIndication routine.
3083 if dh.isReadIndicationRoutineActive {
3084 dh.stopIndications <- true
3085 }
3086 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003087 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303088 }
3089}
kesavand39e0aa32020-01-28 20:58:50 -05003090
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303091func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3092 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3093 if err != nil || device == nil {
3094 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3095 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3096 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3097 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3098 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3099 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3100 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3101 return
3102 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303103 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003104 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303105
3106 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3107 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303108 // First, stop the read indication and heartbeat check routines to prevent any delay
3109 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303110 dh.lockDevice.RLock()
3111 // Stop the read indication only if it the routine is active
3112 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3113 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3114 // on next execution of the readIndication routine.
3115 if dh.isReadIndicationRoutineActive {
3116 dh.stopIndications <- true
3117 }
3118 dh.lockDevice.RUnlock()
3119
bseenivad1c984b2025-01-09 12:54:44 +05303120 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3121 DeviceId: dh.device.Id,
3122 OperStatus: voltha.OperStatus_REBOOTED,
3123 ConnStatus: voltha.ConnectStatus_REACHABLE,
3124 }); err != nil {
3125 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3126 }
3127
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303128 //raise olt communication failure event
3129 raisedTs := time.Now().Unix()
3130 cloned := proto.Clone(device).(*voltha.Device)
3131 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3132 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3133 dh.device = cloned // update local copy of the device
3134 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3135
Gustavo Silva41af9122022-10-11 11:05:13 -03003136 if err := dh.cleanupDeviceResources(ctx); err != nil {
3137 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3138 } else {
3139 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3140 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003141
3142 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303143 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003144 if dh.isCollectorActive {
3145 dh.stopCollector <- true
3146 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303147 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003148 if dh.isHeartbeatCheckActive {
3149 dh.stopHeartbeatCheck <- true
3150 }
3151 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303152
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003153 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303154
Akash Kankanala041a2122024-10-16 15:49:22 +05303155 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303156 dh.adapterPreviouslyConnected = false
3157 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303158 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3159 if err != nil || childDevices == nil {
3160 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3161 continue
3162 }
3163 if len(childDevices.Items) == 0 {
3164 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3165 break
3166 } else {
3167 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3168 time.Sleep(5 * time.Second)
3169 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303170 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303171 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003172 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303173 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3174 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303175}
3176
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303177// EnableOnuSerialNumber to enable onu serial number
3178func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3179 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3180 onuSerialNumber := device.SerialNumber
3181
3182 // fetch interfaceid from PortNo
3183 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3184
3185 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3186 if err != nil {
3187 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3188 log.Fields{
3189 "devicer-id": dh.device.Id,
3190 "serial-number": onuSerialNumber}, err).Log()
3191 }
3192
3193 onuIntf := &oop.InterfaceOnuSerialNumber{
3194 IntfId: ponID,
3195 OnuSerialNumber: sn,
3196 }
3197 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3198
3199 if err != nil {
3200 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3201 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3202 "device-id": dh.device.Id,
3203 "onu-serial-number": onuSerialNumber}, err)
3204 }
3205 return nil
3206}
3207
3208// DisableOnuSerialNumber to disable onu serial number
3209func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3210 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3211 onuSerialNumber := device.SerialNumber
3212 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3213 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3214 if err != nil {
3215 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3216 log.Fields{
3217 "devicer-id": dh.device.Id,
3218 "serial-number": onuSerialNumber}, err).Log()
3219 }
3220
3221 onuIntf := &oop.InterfaceOnuSerialNumber{
3222 OnuSerialNumber: sn,
3223 IntfId: ponID,
3224 }
3225 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3226
3227 if err != nil {
3228 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3229 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3230 "device-id": dh.device.Id,
3231 "onu-serial-number": onuSerialNumber}, err)
3232 }
3233 return nil
3234}
3235
3236// EnableOnu to enable onu
3237func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3238 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3239 onuSerialNumber := device.SerialNumber
3240 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3241 if InCacheOnuDev == nil {
3242 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3243 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3244 "device-id": dh.device.Id,
3245 "onu-serial-number": onuSerialNumber}, nil)
3246 }
3247 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})
3248
3249 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3250 if err != nil {
3251 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3252 log.Fields{
3253 "device-id": dh.device.Id,
3254 "serial-number": onuSerialNumber}, err).Log()
3255 }
3256
3257 onuIntf := &oop.InterfaceOnuSerialNumber{
3258 OnuSerialNumber: sn,
3259 IntfId: InCacheOnuDev.intfID,
3260 }
3261 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3262 OnuId: InCacheOnuDev.onuID,
3263 IntfIdSerialNum: onuIntf,
3264 }
3265 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3266
3267 if err != nil {
3268 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3269 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3270 "olt-device-id": dh.device.Id,
3271 "onu-serial-number": onuSerialNumber}, err)
3272 }
3273 return nil
3274}
3275
3276// DisableOnu to disable onu
3277func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3278 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3279 onuSerialNumber := device.SerialNumber
3280 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3281 if InCacheOnuDev == nil {
3282 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3283 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3284 "device-id": dh.device.Id,
3285 "onu-serial-number": onuSerialNumber}, nil)
3286 }
3287 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})
3288
3289 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3290 if err != nil {
3291 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3292 log.Fields{
3293 "device-id": dh.device.Id,
3294 "serial-number": onuSerialNumber}, err).Log()
3295 }
3296
3297 onuIntf := &oop.InterfaceOnuSerialNumber{
3298 OnuSerialNumber: sn,
3299 IntfId: InCacheOnuDev.intfID,
3300 }
3301 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3302 OnuId: InCacheOnuDev.onuID,
3303 IntfIdSerialNum: onuIntf,
3304 }
3305 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3306
3307 if err != nil {
3308 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3309 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3310 "olt-device-id": dh.device.Id,
3311 "onu-serial-number": onuSerialNumber}, err)
3312 }
3313 return nil
3314}
3315
kesavand39e0aa32020-01-28 20:58:50 -05003316// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003317func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3318 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3319 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003320}
3321
3322// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003323func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3324 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3325 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003326}
3327
Mahir Gunyela2e68702022-12-07 00:00:42 -08003328// 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 +00003329func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3330 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003331 if port.GetType() == voltha.Port_ETHERNET_NNI {
3332 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003333 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303334 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303335 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003336 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003337 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003338 }
3339 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003340 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003341 ponIntf := &oop.Interface{IntfId: ponID}
3342 var operStatus voltha.OperStatus_Types
bseenivaa1622112025-12-11 18:24:02 +05303343 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
kesavand39e0aa32020-01-28 20:58:50 -05003344 if enablePort {
3345 operStatus = voltha.OperStatus_ACTIVE
bseenivaa1622112025-12-11 18:24:02 +05303346 out, err := dh.Client.EnablePonIf(subCtx, ponIntf)
3347 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003348 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303349 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003350 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003351 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003352 }
3353 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003354 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003355 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003356 } else {
3357 operStatus = voltha.OperStatus_UNKNOWN
bseenivaa1622112025-12-11 18:24:02 +05303358 out, err := dh.Client.DisablePonIf(subCtx, ponIntf)
3359 cancel()
kesavand39e0aa32020-01-28 20:58:50 -05003360 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303361 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003362 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003363 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003364 }
3365 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003366 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003367 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003368 }
khenaidoodc2116e2021-10-19 17:33:19 -04003369 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003370 DeviceId: dh.device.Id,
3371 PortType: voltha.Port_PON_OLT,
3372 PortNo: port.PortNo,
3373 OperStatus: operStatus,
3374 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303375 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303376 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003377 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003378 }
3379 return nil
3380}
3381
Mahir Gunyela2e68702022-12-07 00:00:42 -08003382// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003383func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003384 // Disable the port and update the oper_port_status to core
3385 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003386 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003387 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003388 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303389 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303390 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003391 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003392 }
3393 }
3394 }
3395 return nil
3396}
3397
Mahir Gunyela2e68702022-12-07 00:00:42 -08003398// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003399func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3400 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3401 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003402 if port.Type == voltha.Port_ETHERNET_NNI {
3403 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003404 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003405 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003406 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003407 }
3408 }
3409 if port.Type == voltha.Port_PON_OLT {
3410 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003411 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003412 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003413 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003414 }
3415 }
3416 }
3417}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003418
3419// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003420func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003421 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003422 if dh.getDeviceDeletionInProgressFlag() {
3423 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3424 // will reboot, so everything will be reset on the pOLT too.
3425 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3426 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3427 return nil
3428 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303429
3430 if dh.transitionMap.currentDeviceState != deviceStateUp {
3431 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})
3432 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3433 }
3434
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003435 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003436 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003437
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003438 var sn *oop.SerialNumber
3439 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003440 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303441 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003442 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303443 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003444 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003445 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003446
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003447 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303448 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003449 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003450 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3451 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3452 "device-id": dh.device.Id,
3453 "intf-id": intfID,
3454 "onuID": onuID,
3455 "err": err})
3456 } else {
3457 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003458 // Delete flows from device before schedulers and queue
3459 // Clear flowids for gem cache.
3460 removedFlows := []uint64{}
3461 for _, gem := range onuGem.GemPorts {
3462 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3463 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303464 // multiple gem port can have the same flow id
3465 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003466 var alreadyRemoved bool
3467 for _, removedFlowID := range removedFlows {
3468 if removedFlowID == flowID {
3469 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3470 alreadyRemoved = true
3471 break
3472 }
3473 }
3474 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003475 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003476 removedFlows = appendUnique64bit(removedFlows, flowID)
3477 }
3478 }
3479 }
3480 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3481 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003482 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3483 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3484 "device-id": dh.device.Id,
3485 "onu-device": onu,
3486 "err": err})
3487 }
yasin saplibddc2d72022-02-08 13:10:17 +00003488 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003489 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3490 "intf-id": intfID,
3491 "onu-device": onu,
3492 "onu-gem": onuGem,
3493 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303494 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003495 }
3496 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003497 }
yasin saplibddc2d72022-02-08 13:10:17 +00003498 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003499 dh.onus.Delete(onuKey)
3500 dh.discOnus.Delete(onuSn)
3501
bseenivaa1622112025-12-11 18:24:02 +05303502 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003503 // Now clear the ONU on the OLT
bseenivaa1622112025-12-11 18:24:02 +05303504 if _, err := dh.Client.DeleteOnu(subCtx, onu); err != nil {
3505 cancel()
Thomas Lee S94109f12020-03-03 16:39:29 +05303506 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303507 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003508 "onu-id": onuID}, err).Log()
3509 }
bseenivaa1622112025-12-11 18:24:02 +05303510 cancel()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003511 return nil
3512}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003513func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3514 flow := &oop.Flow{FlowId: flowID}
3515 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3516 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3517 "device-id": dh.device.Id})
3518 } else {
3519 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3520 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3521 "device-id": dh.device.Id,
3522 "err": err})
3523 }
3524 }
3525}
Girish Gowdracefae192020-03-19 18:14:10 -07003526
3527func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003528 for _, field := range flow_utils.GetOfbFields(flow) {
3529 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003530 return field.GetPort()
3531 }
3532 }
3533 return InvalidPort
3534}
3535
3536func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003537 for _, action := range flow_utils.GetActions(flow) {
3538 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003539 if out := action.GetOutput(); out != nil {
3540 return out.GetPort()
3541 }
3542 }
3543 }
3544 return InvalidPort
3545}
3546
Girish Gowdracefae192020-03-19 18:14:10 -07003547func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3548 inPort := getInPortFromFlow(flow)
3549 outPort := getOutPortFromFlow(flow)
3550
3551 if inPort == InvalidPort || outPort == InvalidPort {
3552 return inPort, outPort
3553 }
3554
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003555 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003556 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003557 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003558 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003559 return uniPort, outPort
3560 }
3561 }
3562 } else {
3563 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003564 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003565 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003566 return inPort, uniPort
3567 }
3568 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003569 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003570 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003571 return uniPort, outPort
3572 }
3573 }
3574 }
3575
3576 return InvalidPort, InvalidPort
3577}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003578
3579func extractOmciTransactionID(omciPkt []byte) uint16 {
3580 if len(omciPkt) > 3 {
3581 d := omciPkt[0:2]
3582 transid := binary.BigEndian.Uint16(d)
3583 return transid
3584 }
3585 return 0
3586}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003587
3588// StoreOnuDevice stores the onu parameters to the local cache.
3589func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3590 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3591 dh.onus.Store(onuKey, onuDevice)
3592}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003593
khenaidoodc2116e2021-10-19 17:33:19 -04003594func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003595 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003596 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003597 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003598 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003599 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003600 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003601 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003602 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3603 return nil, err
3604 }
3605 ID = device.ProxyAddress.GetOnuId()
3606 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3607 valueparam.Onu = &Onu
3608 valueparam.Value = value
3609
3610 // This API is unsupported until agent patch is added
3611 resp.Unsupported = uint32(value)
3612 _ = ctx
3613
3614 // Uncomment this code once agent changes are complete and tests
3615 /*
3616 resp, err = dh.Client.GetValue(ctx, valueparam)
3617 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003618 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003619 return nil, err
3620 }
3621 */
3622
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003623 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 -08003624 return resp, nil
3625}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003626
Akash Kankanala041a2122024-10-16 15:49:22 +05303627func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003628 // Default to NNI
3629 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003630 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003631 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003632 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003633 }
3634 return intfID
3635}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003636
Akash Kankanala041a2122024-10-16 15:49:22 +05303637func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003638 dh.perPonOnuIndicationChannelLock.Lock()
3639 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3640 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003641 return ch.indicationChannel
3642 }
3643 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303644 // We create a buffered channel here to avoid calling function to be blocked
3645 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003646 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003647 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003648 stopChannel: make(chan struct{}),
3649 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003650 dh.perPonOnuIndicationChannel[intfID] = channels
3651 dh.perPonOnuIndicationChannelLock.Unlock()
3652 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003653 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003654}
3655
Mahir Gunyelb0046752021-02-26 13:51:05 -08003656func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3657 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3658 dh.perPonOnuIndicationChannelLock.Lock()
3659 defer dh.perPonOnuIndicationChannelLock.Unlock()
3660 for _, v := range dh.perPonOnuIndicationChannel {
3661 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003662 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003663 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003664}
3665
Mahir Gunyelb0046752021-02-26 13:51:05 -08003666func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3667 ind := onuIndicationMsg{
3668 ctx: ctx,
3669 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003670 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003671 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003672 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303673 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003674}
3675
Mahir Gunyelb0046752021-02-26 13:51:05 -08003676func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003677 for {
3678 select {
3679 // process one indication per onu, before proceeding to the next one
3680 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003681 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003682 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003683 "ind": indication})
3684 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003685 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003686 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003687 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3688 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003689 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003690 }
3691 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003692 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003693 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3694 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003695 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003696 }
3697 }
3698 case <-onuChannels.stopChannel:
3699 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3700 close(onuChannels.indicationChannel)
3701 return
3702 }
3703 }
3704}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003705
3706// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3707// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003708func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003709 if dh.getDeviceDeletionInProgressFlag() {
3710 // The device itself is going to be reset as part of deletion. So nothing to be done.
3711 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3712 return nil
3713 }
3714
Girish Gowdra491a9c62021-01-06 16:43:07 -08003715 // Step1 : Fill McastFlowOrGroupControlBlock
3716 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3717 // Step3 : Wait on response channel for response
3718 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003719 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003720 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3721 errChan := make(chan error)
3722 var groupID uint32
3723 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3724 ctx: ctx,
3725 flowOrGroupAction: action,
3726 flow: flow,
3727 group: group,
3728 errChan: &errChan,
3729 }
3730 if flow != nil {
3731 groupID = flow_utils.GetGroup(flow)
3732 } else if group != nil {
3733 groupID = group.Desc.GroupId
3734 } else {
3735 return errors.New("flow-and-group-both-nil")
3736 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003737 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3738 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3739 // Derive the appropriate go routine to handle the request by a simple module operation.
3740 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3741 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3742 // Wait for handler to return error value
3743 err := <-errChan
3744 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3745 return err
3746 }
3747 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3748 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003749}
3750
3751// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003752func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003753 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003754 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003755 // block on the channel to receive an incoming mcast flow/group
3756 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003757 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3758 if mcastFlowOrGroupCb.flow != nil {
3759 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3760 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3761 log.Fields{"device-id": dh.device.Id,
3762 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003763 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3764 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3765 for _, flMgr := range dh.flowMgr {
3766 if flMgr != nil {
3767 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3768 break
3769 }
3770 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003771 // Pass the return value over the return channel
3772 *mcastFlowOrGroupCb.errChan <- err
3773 } else { // flow remove
3774 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3775 log.Fields{"device-id": dh.device.Id,
3776 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003777 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3778 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3779 for _, flMgr := range dh.flowMgr {
3780 if flMgr != nil {
3781 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3782 break
3783 }
3784 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003785 // Pass the return value over the return channel
3786 *mcastFlowOrGroupCb.errChan <- err
3787 }
3788 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303789 switch mcastFlowOrGroupCb.flowOrGroupAction {
3790 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003791 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3792 log.Fields{"device-id": dh.device.Id,
3793 "groupToAdd": mcastFlowOrGroupCb.group})
3794 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3795 // Pass the return value over the return channel
3796 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303797 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003798 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3799 log.Fields{"device-id": dh.device.Id,
3800 "groupToModify": mcastFlowOrGroupCb.group})
3801 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3802 // Pass the return value over the return channel
3803 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303804 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003805 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3806 log.Fields{"device-id": dh.device.Id,
3807 "groupToRemove": mcastFlowOrGroupCb.group})
3808 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3809 // Pass the return value over the return channel
3810 *mcastFlowOrGroupCb.errChan <- err
3811 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003812 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003813 case <-stopHandler:
3814 dh.mcastHandlerRoutineActive[routineIndex] = false
3815 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003816 }
3817 }
3818}
kesavand62126212021-01-12 04:56:06 -05003819
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003820// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003821func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003822 for i, v := range dh.stopMcastHandlerRoutine {
3823 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003824 select {
3825 case v <- true:
3826 case <-time.After(time.Second * 5):
3827 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3828 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003829 }
3830 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003831
3832 if dh.incomingMcastFlowOrGroup != nil {
3833 for k := range dh.incomingMcastFlowOrGroup {
3834 if dh.incomingMcastFlowOrGroup[k] != nil {
3835 dh.incomingMcastFlowOrGroup[k] = nil
3836 }
3837 }
3838 dh.incomingMcastFlowOrGroup = nil
3839 }
3840
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003841 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003842 logger.Debug(ctx, "stopped all mcast handler routines")
3843}
3844
Akash Kankanala041a2122024-10-16 15:49:22 +05303845// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003846func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003847 singleValResp := extension.SingleGetValueResponse{
3848 Response: &extension.GetValueResponse{
3849 Response: &extension.GetValueResponse_PortCoutners{
3850 PortCoutners: &extension.GetOltPortCountersResponse{},
3851 },
3852 },
3853 }
3854
Akash Kankanala041a2122024-10-16 15:49:22 +05303855 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003856 return &extension.SingleGetValueResponse{
3857 Response: &extension.GetValueResponse{
3858 Status: status,
3859 ErrReason: reason,
3860 },
3861 }
3862 }
3863
3864 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3865 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303866 // send error response
kesavand62126212021-01-12 04:56:06 -05003867 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3868 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3869 }
3870 statIndChn := make(chan bool, 1)
3871 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3872 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303873 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003874
3875 go func() {
bseenivaa1622112025-12-11 18:24:02 +05303876 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3877 _, err := dh.Client.CollectStatistics(subCtx, new(oop.Empty))
kesavand62126212021-01-12 04:56:06 -05003878 if err != nil {
3879 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3880 }
bseenivaa1622112025-12-11 18:24:02 +05303881 cancel()
kesavand62126212021-01-12 04:56:06 -05003882 }()
3883 select {
3884 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303885 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003886 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3887 case <-time.After(oltPortInfoTimeout * time.Second):
3888 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3889 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3890 case <-ctx.Done():
3891 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3892 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3893 }
mgouda86543582025-10-29 20:58:16 +05303894 switch oltPortInfo.PortType {
3895 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303896 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003897 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003898 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3899 cmnni := dh.portStats.collectNNIMetrics(intfID)
3900 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303901 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003902 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3903 }
3904 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3905 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303906 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003907 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003908 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003909 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3910 cmpon := dh.portStats.collectPONMetrics(intfID)
3911 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303912 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003913 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3914 }
3915 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3916 return &singleValResp
3917 }
3918 }
3919 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3920}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303921
Akash Kankanala041a2122024-10-16 15:49:22 +05303922//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303923func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303924 singleValResp := extension.SingleGetValueResponse{
3925 Response: &extension.GetValueResponse{
3926 Status: extension.GetValueResponse_OK,
3927 Response: &extension.GetValueResponse_OffloadedAppsStats{
3928 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3929 },
3930 },
3931 }
3932
3933 return &singleValResp
3934}
3935
Akash Kankanala041a2122024-10-16 15:49:22 +05303936//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303937func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303938 singleValResp := extension.SingleSetValueResponse{
3939 Response: &extension.SetValueResponse{
3940 Status: extension.SetValueResponse_OK,
3941 },
3942 }
3943
3944 return &singleValResp
3945}
3946
Akash Kankanala041a2122024-10-16 15:49:22 +05303947//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303948func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303949 singleValResp := extension.SingleSetValueResponse{
3950 Response: &extension.SetValueResponse{
3951 Status: extension.SetValueResponse_OK,
3952 },
3953 }
3954
3955 return &singleValResp
3956}
3957
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303958func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303959 singleValResp := extension.SingleGetValueResponse{
3960 Response: &extension.GetValueResponse{
3961 Response: &extension.GetValueResponse_OnuPonCounters{
3962 OnuPonCounters: &extension.GetOnuCountersResponse{},
3963 },
3964 },
3965 }
3966
Akash Kankanala041a2122024-10-16 15:49:22 +05303967 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303968 return &extension.SingleGetValueResponse{
3969 Response: &extension.GetValueResponse{
3970 Status: status,
3971 ErrReason: reason,
3972 },
3973 }
3974 }
3975 intfID := onuPonInfo.IntfId
3976 onuID := onuPonInfo.OnuId
3977 onuKey := dh.formOnuKey(intfID, onuID)
3978
3979 if _, ok := dh.onus.Load(onuKey); !ok {
3980 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3981 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3982 }
3983 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3984 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3985 if cmnni == nil {
3986 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3987 }
3988 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3989 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303990}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003991
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303992func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3993 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3994 if err != nil {
3995 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3996 return nil, err
3997 }
3998 if onuGemInfo != nil {
3999 if len(onuGemInfo.UniPorts) == 0 {
4000 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
4001 return nil, err
4002 }
4003 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
4004 return onuGemInfo, nil
4005 }
4006 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
4007 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
4008}
4009
4010func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
4011 var err error
4012 var allocStats *oop.OnuAllocIdStatistics
4013 var onuGemStats *oop.GemPortStatistics
4014 for _, uni := range onuGemInfo.UniPorts {
4015 uniID := plt.UniIDFromPortNum(uni)
4016 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
4017 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
4018 if len(tpIDs) == 0 {
4019 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
4020 continue
4021 }
4022 for _, tpId := range tpIDs {
4023 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
4024 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
4025 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
4026 if techProfileInstance != nil {
4027 switch tpInst := techProfileInstance.(type) {
4028 case *tp_pb.TechProfileInstance:
4029 allocId := tpInst.UsScheduler.AllocId
4030 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
bseenivaa1622112025-12-11 18:24:02 +05304031 allocCtx, allocCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4032 allocStats, err = dh.Client.GetAllocIdStatistics(allocCtx, &onuAllocPkt)
4033 allocCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304034 if err != nil {
4035 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
4036 return err
4037 }
4038 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
4039 allocIdInfo.AllocId = allocStats.AllocId
4040 allocIdInfo.RxBytes = allocStats.RxBytes
4041
4042 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
4043
4044 gemPorts := tpInst.UpstreamGemPortAttributeList
4045 for _, gem := range gemPorts {
4046 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
bseenivaa1622112025-12-11 18:24:02 +05304047 gemCtx, gemCtxcancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4048 onuGemStats, err = dh.Client.GetGemPortStatistics(gemCtx, &onuGemPkt)
4049 gemCtxcancel()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05304050 if err != nil {
4051 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
4052 return err
4053 }
4054 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
4055 gemStatsInfo.GemId = onuGemStats.GemportId
4056 gemStatsInfo.RxBytes = onuGemStats.RxBytes
4057 gemStatsInfo.RxPackets = onuGemStats.RxPackets
4058 gemStatsInfo.TxBytes = onuGemStats.TxBytes
4059 gemStatsInfo.TxPackets = onuGemStats.TxPackets
4060
4061 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
4062 }
4063 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
4064
4065 default:
4066 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4067 return err
4068 }
4069 } else {
4070 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4071 continue
4072 }
4073 }
4074 }
4075 return err
4076}
4077
4078//nolint:unparam
4079func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4080 singleValResp := extension.SingleGetValueResponse{
4081 Response: &extension.GetValueResponse{
4082 Status: extension.GetValueResponse_OK,
4083 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4084 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4085 },
4086 },
4087 }
4088 errResp := func(status extension.GetValueResponse_Status,
4089 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4090 return &extension.SingleGetValueResponse{
4091 Response: &extension.GetValueResponse{
4092 Status: status,
4093 ErrReason: reason,
4094 },
4095 }
4096 }
4097
4098 var intfID, onuID uint32
4099 if onuDevice != nil {
4100 onuID = onuDevice.ProxyAddress.OnuId
4101 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4102 }
4103
4104 onuKey := dh.formOnuKey(intfID, onuID)
4105 if _, ok := dh.onus.Load(onuKey); !ok {
4106 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4107 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4108 }
4109 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4110
4111 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4112 if err == nil {
4113 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4114 if err != nil {
4115 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4116 }
4117 } else {
4118 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4119 }
4120 return &singleValResp
4121}
4122
nikesh.krishnanc8473432023-06-14 12:14:54 +05304123func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304124 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
bseenivaa1622112025-12-11 18:24:02 +05304125 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4126 OnuInfo, err := dh.Client.GetOnuInfo(subCtx, &Onu)
4127 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304128 if err != nil {
4129 return nil, err
4130 }
4131 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304132}
4133
4134func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304135 Intf := oop.Interface{IntfId: intfID}
bseenivaa1622112025-12-11 18:24:02 +05304136 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4137 IntfInfo, err := dh.Client.GetPonInterfaceInfo(subCtx, &Intf)
4138 cancel()
nikesh.krishnanc8473432023-06-14 12:14:54 +05304139 if err != nil {
4140 return nil, err
4141 }
4142 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304143}
4144
Gamze Abaka85e9a142021-05-26 13:41:39 +00004145func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004146 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
bseenivaa1622112025-12-11 18:24:02 +05304147 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4148 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4149 cancel()
Gamze Abaka85e9a142021-05-26 13:41:39 +00004150 if err != nil {
4151 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4152 return generateSingleGetValueErrorResponse(err)
4153 }
4154 return &extension.SingleGetValueResponse{
4155 Response: &extension.GetValueResponse{
4156 Status: extension.GetValueResponse_OK,
4157 Response: &extension.GetValueResponse_RxPower{
4158 RxPower: &extension.GetRxPowerResponse{
4159 IntfId: rxPowerRequest.IntfId,
4160 OnuId: rxPowerRequest.OnuId,
4161 Status: rxPower.Status,
4162 FailReason: rxPower.FailReason.String(),
4163 RxPower: rxPower.RxPowerMeanDbm,
4164 },
4165 },
4166 },
4167 }
4168}
4169
praneeth nalmas55616d62023-02-06 09:19:18 +05304170func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304171 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304172 return &extension.SingleGetValueResponse{
4173 Response: &extension.GetValueResponse{
4174 Status: status,
4175 ErrReason: reason,
4176 },
4177 }
4178 }
4179
4180 resp := extension.SingleGetValueResponse{
4181 Response: &extension.GetValueResponse{
4182 Status: extension.GetValueResponse_OK,
4183 Response: &extension.GetValueResponse_OltRxPower{
4184 OltRxPower: &extension.GetOltRxPowerResponse{},
4185 },
4186 },
4187 }
4188
4189 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4190 portLabel := OltRxPowerRequest.PortLabel
4191 serialNumber := OltRxPowerRequest.OnuSn
4192
4193 portInfo := strings.Split(portLabel, "-")
4194 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4195
4196 if err != nil {
4197 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4198 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4199 }
4200
4201 if portInfo[0] != "pon" {
4202 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4203 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4204 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304205
4206 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304207 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4208 if onuDev != nil {
bseenivaa1622112025-12-11 18:24:02 +05304209 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
praneeth nalmas55616d62023-02-06 09:19:18 +05304210 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
bseenivaa1622112025-12-11 18:24:02 +05304211 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4212 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304213 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304214 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4215 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304216 }
4217
4218 rxPowerValue := extension.RxPower{}
4219 rxPowerValue.OnuSn = onuDev.serialNumber
4220 rxPowerValue.Status = rxPower.GetStatus()
4221 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4222 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4223
4224 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304225 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304226 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4227 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4228 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304229 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304230 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304231 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304232 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
bseenivaa1622112025-12-11 18:24:02 +05304233 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4234 rxPower, err := dh.Client.GetPonRxPower(subCtx, &Onu)
4235 cancel()
praneeth nalmas55616d62023-02-06 09:19:18 +05304236 if err != nil {
4237 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4238 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304239 rxPowerValue := extension.RxPower{}
4240 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4241 rxPowerValue.Status = rxPower.GetStatus()
4242 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4243 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4244
4245 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4246 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304247 }
4248 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4249 return true
4250 })
4251 }
4252 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4253 return &resp
4254}
4255
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304256func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4257 errResp := func(status extension.GetValueResponse_Status,
4258 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4259 return &extension.SingleGetValueResponse{
4260 Response: &extension.GetValueResponse{
4261 Status: status,
4262 ErrReason: reason,
4263 },
4264 }
4265 }
4266
4267 resp := extension.SingleGetValueResponse{
4268 Response: &extension.GetValueResponse{
4269 Status: extension.GetValueResponse_OK,
4270 Response: &extension.GetValueResponse_OltPonStatsResponse{
4271 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4272 },
4273 },
4274 }
4275
4276 portLabel := ponStatsRequest.GetPortLabel()
4277 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4278
4279 portInfo := strings.Split(portLabel, "-")
4280 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4281
4282 if err != nil {
4283 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4284 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4285 }
4286
4287 if portInfo[0] != "pon" {
4288 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4289 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4290 }
4291
4292 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304293 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4294 ponStats, err := dh.Client.GetPonPortStatistics(subCtx, &Interface)
4295 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304296 if err != nil {
4297 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4298 return generateSingleGetValueErrorResponse(err)
4299 }
4300
4301 ponPortStats := resp.Response.GetOltPonStatsResponse()
4302 ponPortStats.PonPort = uint32(portNumber)
4303 ponPortStats.PortStatistics = ponStats
4304
4305 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4306 return &resp
4307}
4308
4309func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4310 errResp := func(status extension.GetValueResponse_Status,
4311 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4312 return &extension.SingleGetValueResponse{
4313 Response: &extension.GetValueResponse{
4314 Status: status,
4315 ErrReason: reason,
4316 },
4317 }
4318 }
4319
4320 resp := extension.SingleGetValueResponse{
4321 Response: &extension.GetValueResponse{
4322 Status: extension.GetValueResponse_OK,
4323 Response: &extension.GetValueResponse_OltNniStatsResponse{
4324 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4325 },
4326 },
4327 }
4328
4329 portLabel := nniStatsRequest.GetPortLabel()
4330 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4331
4332 portInfo := strings.Split(portLabel, "-")
4333 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4334
4335 if err != nil {
4336 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4337 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4338 }
4339
4340 if portInfo[0] != "nni" {
4341 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4342 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4343 }
4344
4345 Interface := oop.Interface{IntfId: uint32(portNumber)}
bseenivaa1622112025-12-11 18:24:02 +05304346 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4347 nniStats, err := dh.Client.GetNniPortStatistics(subCtx, &Interface)
4348 cancel()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304349 if err != nil {
4350 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4351 return generateSingleGetValueErrorResponse(err)
4352 }
4353
4354 nniPortStats := resp.Response.GetOltNniStatsResponse()
4355 nniPortStats.NniPort = uint32(portNumber)
4356 nniPortStats.PortStatistics = nniStats
4357
4358 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4359 return &resp
4360}
4361
Akash Kankanala041a2122024-10-16 15:49:22 +05304362// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004363func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304364 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004365 return &extension.SingleGetValueResponse{
4366 Response: &extension.GetValueResponse{
4367 Status: status,
4368 ErrReason: reason,
4369 },
4370 }
4371 }
4372
4373 if err != nil {
4374 if e, ok := status.FromError(err); ok {
4375 switch e.Code() {
4376 case codes.Internal:
4377 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4378 case codes.DeadlineExceeded:
4379 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4380 case codes.Unimplemented:
4381 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4382 case codes.NotFound:
4383 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4384 }
4385 }
4386 }
4387
4388 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4389}
khenaidoo106c61a2021-08-11 18:05:46 -04004390
4391/*
4392Helper functions to communicate with Core
4393*/
4394
4395func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4396 cClient, err := dh.coreClient.GetCoreServiceClient()
4397 if err != nil || cClient == nil {
4398 return nil, err
4399 }
4400 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4401 defer cancel()
4402 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4403}
4404
khenaidoodc2116e2021-10-19 17:33:19 -04004405func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004406 cClient, err := dh.coreClient.GetCoreServiceClient()
4407 if err != nil || cClient == nil {
4408 return nil, err
4409 }
4410 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4411 defer cancel()
4412 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4413}
4414
khenaidoodc2116e2021-10-19 17:33:19 -04004415func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004416 cClient, err := dh.coreClient.GetCoreServiceClient()
4417 if err != nil || cClient == nil {
4418 return err
4419 }
4420 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4421 defer cancel()
4422 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4423 return err
4424}
4425
4426func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4427 cClient, err := dh.coreClient.GetCoreServiceClient()
4428 if err != nil || cClient == nil {
4429 return nil, err
4430 }
4431 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4432 defer cancel()
4433 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4434}
4435
4436func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4437 cClient, err := dh.coreClient.GetCoreServiceClient()
4438 if err != nil || cClient == nil {
4439 return nil, err
4440 }
4441 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4442 defer cancel()
4443 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4444}
4445
4446func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4447 cClient, err := dh.coreClient.GetCoreServiceClient()
4448 if err != nil || cClient == nil {
4449 return err
4450 }
4451 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4452 defer cancel()
4453 _, err = cClient.DeviceUpdate(subCtx, device)
4454 return err
4455}
4456
khenaidoodc2116e2021-10-19 17:33:19 -04004457func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004458 cClient, err := dh.coreClient.GetCoreServiceClient()
4459 if err != nil || cClient == nil {
4460 return nil, err
4461 }
4462 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4463 defer cancel()
4464 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4465}
4466
khenaidoodc2116e2021-10-19 17:33:19 -04004467func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004468 cClient, err := dh.coreClient.GetCoreServiceClient()
4469 if err != nil || cClient == nil {
4470 return err
4471 }
4472 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4473 defer cancel()
4474 _, err = cClient.SendPacketIn(subCtx, pkt)
4475 return err
4476}
4477
4478func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4479 cClient, err := dh.coreClient.GetCoreServiceClient()
4480 if err != nil || cClient == nil {
4481 return err
4482 }
4483 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4484 defer cancel()
4485 _, err = cClient.PortCreated(subCtx, port)
4486 return err
4487}
4488
khenaidoodc2116e2021-10-19 17:33:19 -04004489func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004490 cClient, err := dh.coreClient.GetCoreServiceClient()
4491 if err != nil || cClient == nil {
4492 return err
4493 }
4494 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4495 defer cancel()
4496 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4497 return err
4498}
4499
khenaidoodc2116e2021-10-19 17:33:19 -04004500func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004501 cClient, err := dh.coreClient.GetCoreServiceClient()
4502 if err != nil || cClient == nil {
4503 return err
4504 }
4505 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4506 defer cancel()
4507 _, err = cClient.PortStateUpdate(subCtx, portState)
4508 return err
4509}
4510
khenaidoodc2116e2021-10-19 17:33:19 -04004511func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004512 cClient, err := dh.coreClient.GetCoreServiceClient()
4513 if err != nil || cClient == nil {
4514 return nil, err
4515 }
4516 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4517 defer cancel()
4518 return cClient.GetDevicePort(subCtx, portFilter)
4519}
4520
nikesh.krishnanc8473432023-06-14 12:14:54 +05304521func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4522 cClient, err := dh.coreClient.GetCoreServiceClient()
4523 if err != nil || cClient == nil {
4524 return nil, err
4525 }
4526 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4527 defer cancel()
4528 return cClient.GetPorts(subCtx, portFilter)
4529}
4530
khenaidoo106c61a2021-08-11 18:05:46 -04004531/*
4532Helper functions to communicate with child adapter
4533*/
4534
khenaidoodc2116e2021-10-19 17:33:19 -04004535func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004536 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4537 if err != nil || aClient == nil {
4538 return err
4539 }
4540 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4541 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4542 defer cancel()
4543 _, err = aClient.OmciIndication(subCtx, response)
4544 return err
4545}
4546
khenaidoodc2116e2021-10-19 17:33:19 -04004547func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004548 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4549 if err != nil || aClient == nil {
4550 return err
4551 }
4552 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4553 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4554 defer cancel()
4555 _, err = aClient.OnuIndication(subCtx, onuInd)
4556 return err
4557}
4558
khenaidoodc2116e2021-10-19 17:33:19 -04004559func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004560 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4561 if err != nil || aClient == nil {
4562 return err
4563 }
4564 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4565 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4566 defer cancel()
4567 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4568 return err
4569}
4570
khenaidoodc2116e2021-10-19 17:33:19 -04004571func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004572 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4573 if err != nil || aClient == nil {
4574 return err
4575 }
4576 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4577 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4578 defer cancel()
4579 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4580 return err
4581}
4582
khenaidoodc2116e2021-10-19 17:33:19 -04004583func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004584 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4585 if err != nil || aClient == nil {
4586 return err
4587 }
4588 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4589 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4590 defer cancel()
4591 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4592 return err
4593}
4594
4595/*
4596Helper functions for remote communication
4597*/
4598
4599// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4600// supports is deleted
4601func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4602 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4603
4604 dh.lockChildAdapterClients.Lock()
4605 defer dh.lockChildAdapterClients.Unlock()
4606 if _, ok := dh.childAdapterClients[endpoint]; ok {
4607 // Already set
4608 return nil
4609 }
4610
4611 // Setup child's adapter grpc connection
4612 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004613 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4614 dh.cfg.AdapterEndpoint,
4615 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004616 "onu_inter_adapter_service.OnuInterAdapterService",
4617 dh.onuInterAdapterRestarted,
4618 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004619 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4620 return err
4621 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304622 retryCodes := []codes.Code{
4623 codes.Unavailable, // server is currently unavailable
4624 codes.DeadlineExceeded, // deadline for the operation was exceeded
4625 }
4626 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4627 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 -04004628
nikesh.krishnand9812542023-08-01 18:31:39 +05304629 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004630 // Wait until we have a connection to the child adapter.
4631 // Unlimited retries or until context expires
4632 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4633 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4634 for {
4635 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4636 if err == nil && client != nil {
4637 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4638 break
4639 }
4640 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4641 // Backoff
4642 if err = backoff.Backoff(subCtx); err != nil {
4643 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4644 break
4645 }
4646 }
4647 return nil
4648}
4649
khenaidoodc2116e2021-10-19 17:33:19 -04004650func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004651 // First check from cache
4652 dh.lockChildAdapterClients.RLock()
4653 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4654 dh.lockChildAdapterClients.RUnlock()
4655 return cgClient.GetOnuInterAdapterServiceClient()
4656 }
4657 dh.lockChildAdapterClients.RUnlock()
4658
4659 // Set the child connection - can occur on restarts
4660 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4661 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4662 cancel()
4663 if err != nil {
4664 return nil, err
4665 }
4666
4667 // Get the child client now
4668 dh.lockChildAdapterClients.RLock()
4669 defer dh.lockChildAdapterClients.RUnlock()
4670 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4671 return cgClient.GetOnuInterAdapterServiceClient()
4672 }
4673 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4674}
4675
4676func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4677 dh.lockChildAdapterClients.Lock()
4678 defer dh.lockChildAdapterClients.Unlock()
4679 for key, client := range dh.childAdapterClients {
4680 client.Stop(ctx)
4681 delete(dh.childAdapterClients, key)
4682 }
4683}
4684
khenaidooefff76e2021-12-15 16:51:30 -05004685// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4686func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4687 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004688 return nil
4689}
4690
khenaidooefff76e2021-12-15 16:51:30 -05004691// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4692func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4693 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004694 return nil
4695 }
khenaidooefff76e2021-12-15 16:51:30 -05004696 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004697}
Girish Gowdra950326e2021-11-05 12:43:24 -07004698
4699func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4700 dh.lockDevice.Lock()
4701 defer dh.lockDevice.Unlock()
4702 dh.isDeviceDeletionInProgress = flag
4703}
4704
4705func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4706 dh.lockDevice.RLock()
4707 defer dh.lockDevice.RUnlock()
4708 return dh.isDeviceDeletionInProgress
4709}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004710
4711// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4712// Returns false if waiting timed out.
4713func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4714 c := make(chan struct{})
4715 go func() {
4716 defer close(c)
4717 wg.Wait()
4718 }()
4719 select {
4720 case <-c:
4721 return true // completed normally
4722 case <-time.After(timeout):
4723 return false // timed out
4724 }
4725}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304726
4727func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4728 val, err := json.Marshal(signature)
4729 if err != nil {
4730 logger.Error(ctx, "failed-to-marshal")
4731 return
4732 }
4733 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4734 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4735 }
4736}
4737
4738func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4739 var signature uint32
4740
4741 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4742 if er == nil {
4743 if Value != nil {
4744 Val, er := kvstore.ToByte(Value.Value)
4745 if er != nil {
4746 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4747 return signature
4748 }
4749 if er = json.Unmarshal(Val, &signature); er != nil {
4750 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4751 return signature
4752 }
4753 }
4754 }
4755 return signature
4756}