blob: c85be74e6da9a3e0d8fd0889486ddb53e2b5fc20 [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
285func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
286 if dh.resourceMgr != nil {
287 for _, rscMgr := range dh.resourceMgr {
288 if rscMgr != nil {
289 rscMgr.CloseKVClient(ctx)
290 }
291 }
292 }
293 if dh.flowMgr != nil {
294 for _, flMgr := range dh.flowMgr {
295 if flMgr != nil {
296 flMgr.CloseKVClient(ctx)
297 }
298 }
299 }
300}
301
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530302// start save the device to the data model
303func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700304 dh.lockDevice.Lock()
305 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000306 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700307 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000308 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530309}
310
khenaidooefff76e2021-12-15 16:51:30 -0500311// Stop stops the device handler
312func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700313 dh.lockDevice.Lock()
314 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000315 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500316 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400317
khenaidooefff76e2021-12-15 16:51:30 -0500318 // Delete (which will stop also) all grpc connections to the child adapters
319 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530321}
322
ssiddiqui04386ee2021-08-23 21:58:25 +0530323func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
324 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
325 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
326 if pooledIntfID == intfID {
327 return resourceRanges.GetTechnology()
328 }
329 }
330 }
331 return ""
332}
333
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400334func macifyIP(ip net.IP) string {
335 if len(ip) > 0 {
336 oct1 := strconv.FormatInt(int64(ip[12]), 16)
337 oct2 := strconv.FormatInt(int64(ip[13]), 16)
338 oct3 := strconv.FormatInt(int64(ip[14]), 16)
339 oct4 := strconv.FormatInt(int64(ip[15]), 16)
340 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
341 }
342 return ""
343}
344
Neha Sharma96b7bf22020-06-15 10:37:32 +0000345func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400346 var genmac string
347 var addr net.IP
348 var ips []string
349 var err error
350
Neha Sharma96b7bf22020-06-15 10:37:32 +0000351 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400352
353 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400355
356 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000357 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400358 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000359 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400360 }
361 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000362 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530363 log.Fields{"host": ips[0],
364 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400365 return genmac, nil
366 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000367 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400368 }
369
370 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000371 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530372 log.Fields{"host": host,
373 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400374 return genmac, nil
375}
376
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530377func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700378 slist := strings.Split(mac, ":")
379 result := make([]uint32, len(slist))
380 var err error
381 var tmp int64
382 for index, val := range slist {
383 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
384 return []uint32{1, 2, 3, 4, 5, 6}
385 }
386 result[index] = uint32(tmp)
387 }
388 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530389}
390
Mahir Gunyela2e68702022-12-07 00:00:42 -0800391// 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 -0800392func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800393 switch portType {
394 case voltha.Port_ETHERNET_NNI:
395 return fmt.Sprintf("nni-%d", portNum), nil
396 case voltha.Port_PON_OLT:
397 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700398 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800399
Girish Kumarf26e4882020-03-05 06:49:10 +0000400 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530401}
402
Elia Battiston596406d2022-02-02 12:19:00 +0100403func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
404 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530405 // In case it was not set in the indication
406 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100407 speedMbps = defaultPortSpeedMbps
408 }
409
410 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
411 switch speedMbps {
412 case 1000000:
413 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
414 case 100000:
415 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
416 case 40000:
417 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
418 case 10000:
419 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
420 case 1000:
421 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
422 case 100:
423 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
424 case 10:
425 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
426 }
427
428 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
429
430 port := &of.OfpPort{
431 HwAddr: macAddressToUint32Array(macAddress),
432 Config: 0,
433 State: uint32(of.OfpPortState_OFPPS_LIVE),
434 Curr: capacity,
435 Advertised: capacity,
436 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530437 CurrSpeed: speedMbps * 1000, // kbps
438 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100439 }
440
441 return port
442}
443
444func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000445 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700446 if state == "up" {
447 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530448 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500449 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700450 } else {
451 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500452 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700453 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700454 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400455 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800456 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000457 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400458 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500459
khenaidoo106c61a2021-08-11 18:05:46 -0400460 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400461 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400462 DeviceId: dh.device.Id,
463 Port: portNum,
464 })
465 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000466 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400467 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400468 DeviceId: dh.device.Id,
469 PortType: portType,
470 PortNo: portNum,
471 OperStatus: operStatus})
472 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400473 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
474 "device-id": dh.device.Id,
475 "port-type": portType,
476 "port-number": portNum,
477 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500478 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400479 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500480 }
khenaidoo106c61a2021-08-11 18:05:46 -0400481
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400482 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400483 port = &voltha.Port{
484 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700485 PortNo: portNum,
486 Label: label,
487 Type: portType,
488 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100489 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700490 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000491 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700492 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400493 err = dh.createPortInCore(ctx, port)
494 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000495 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800496 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000497 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400498 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000499 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530500 return nil
501}
502
Kent Hagermane6ff1012020-07-14 15:07:53 -0400503func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400504 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530505 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400506 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
507 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530508 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800509 dh.lockDevice.Lock()
510 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530511 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530512}
513
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700514// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530515// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800516func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000517 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700518 defer func() {
519 dh.lockDevice.Lock()
520 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530521 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700522 dh.lockDevice.Unlock()
523 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700524 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700525 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700526 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700527 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400528
David Bainbridgef5879ca2019-12-13 21:17:54 +0000529 // Create an exponential backoff around re-enabling indications. The
530 // maximum elapsed time for the back off is set to 0 so that we will
531 // continue to retry. The max interval defaults to 1m, but is set
532 // here for code clarity
533 indicationBackoff := backoff.NewExponentialBackOff()
534 indicationBackoff.MaxElapsedTime = 0
535 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700536
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700537 dh.lockDevice.Lock()
538 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530539 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700540 dh.lockDevice.Unlock()
541
Girish Gowdra3f974912020-03-23 20:35:18 -0700542Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700543 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400544 select {
545 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000546 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700547 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400548 default:
549 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100550
551 select {
552 case <-indications.Context().Done():
553 if err != nil {
554 logger.Warnw(ctx, "error-during-enable-indications",
555 log.Fields{"err": err,
556 "device-id": dh.device.Id})
557 }
558
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400559 // Use an exponential back off to prevent getting into a tight loop
560 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100561 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
562 "device-id": dh.device.Id,
563 "duration": duration,
564 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400565 if duration == backoff.Stop {
566 // If we reach a maximum then warn and reset the backoff
567 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100568 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530569 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530570 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400571 indicationBackoff.Reset()
572 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700573
574 // On failure process a backoff timer while watching for stopIndications
575 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700576 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700577 select {
578 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000579 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700580 if !backoffTimer.Stop() {
581 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700582 }
583 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700584 case <-backoffTimer.C:
585 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700586 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700587 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
588 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400589 }
590 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100591 default:
592 if err != nil {
593 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530594 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530595 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100596 // Close the stream, and re-initialize it
597 if err = indications.CloseSend(); err != nil {
598 // Ok to ignore here, because we landed here due to a problem on the stream
599 // In all probability, the closeSend call may fail
600 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
601 log.Fields{"err": err,
602 "device-id": dh.device.Id})
603 }
604 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
605 return err
606 }
607 // once we re-initialized the indication stream, continue to read indications
608 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700609 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100610 // Reset backoff if we have a successful receive
611 indicationBackoff.Reset()
612 // When OLT is admin down, ignore all indications.
613 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
614 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
615 log.Fields{"indication": indication,
616 "device-id": dh.device.Id})
617 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700618 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100619 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530620 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700621 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700623 // Close the send stream
624 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700625
Girish Gowdra3f974912020-03-23 20:35:18 -0700626 return nil
627}
628
629func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700630 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700631 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
632 if err != nil {
633 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
634 }
635 if indications == nil {
636 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
637 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700638 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700639 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400640}
641
642// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
643func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
644 switch indication.Data.(type) {
645 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
646 return true
647
648 default:
649 return false
650 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651}
652
David K. Bainbridge794735f2020-02-11 21:01:37 -0800653func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700654 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000655 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530656 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530658 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000660 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000661 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530662 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000663 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800664 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000665 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800666 }
667 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668}
669
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530670func (dh *DeviceHandler) handleOnuDisableIndication(ctx context.Context, onuIndication *oop.OnuDisabledIndication) error {
671 logger.Infow(ctx, "handleOnuDisableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
672 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
673 intfID := onuIndication.GetIntfId()
674 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
675 onuDev := dh.getChildDevice(ctx, sn, ponPort)
676 if onuDev == nil {
677 logger.Warnw(ctx, "handleOnuDisableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
678 onuDev = &OnuDevice{
679 serialNumber: sn,
680 }
681 }
682 dh.discOnus.Delete(sn)
683
684 raisedTs := time.Now().Unix()
685 if err := dh.eventMgr.onuDisableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
686 return olterrors.NewErrAdapter("failed-indication", log.Fields{
687 "device-id": dh.device.Id,
688 "indication": onuIndication,
689 "timestamp": raisedTs}, err)
690 }
691 OnuIndication := generateOnuIndication(onuDev.intfID, onuDev.onuID, "down", "down")
692 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDev.adapterEndpoint, &ia.OnuIndicationMessage{
693 DeviceId: onuDev.deviceID,
694 OnuIndication: OnuIndication.GetOnuInd(),
695 })
696 if err != nil {
697 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
698 "onu-indicator": OnuIndication.GetOnuInd(),
699 "source": dh.openOLT.config.AdapterEndpoint,
700 "device-type": onuDev.deviceType,
701 "device-id": onuDev.deviceID}, err)
702 }
703 return nil
704}
705
706func (dh *DeviceHandler) handleOnuEnableIndication(ctx context.Context, onuIndication *oop.OnuEnabledIndication) error {
707 logger.Infow(ctx, "handleOnuEnableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
708 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
709 intfID := onuIndication.GetIntfId()
710 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
711 onuDev := dh.getChildDevice(ctx, sn, ponPort)
712 if onuDev == nil {
713 logger.Warnw(ctx, "handleOnuEnableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
714 onuDev = &OnuDevice{
715 serialNumber: sn,
716 }
717 }
718 raisedTs := time.Now().Unix()
719
720 if err := dh.eventMgr.onuEnableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
721 return olterrors.NewErrAdapter("failed-indication", log.Fields{
722 "device-id": dh.device.Id,
723 "indication": onuIndication,
724 "timestamp": raisedTs}, err)
725 }
726 return nil
727}
728
Akash Kankanala041a2122024-10-16 15:49:22 +0530729// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530730func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700731 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 switch indication.Data.(type) {
733 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000734 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
735 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700736 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 -0800737 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400738 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800739 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000741 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
742 defer span.Finish()
743
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700744 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800745 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100746 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400747 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800748 }
749 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000750 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000752 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
753 defer span.Finish()
754
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700755 intfOperInd := indication.GetIntfOperInd()
756 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800757 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100758 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400759 _ = 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 -0800760 }
761 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762 } else if intfOperInd.GetType() == "pon" {
763 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
764 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800765 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100766 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400767 _ = 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 -0800768 }
769 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000770 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700771 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530773 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530774 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700775 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000776 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
777 defer span.Finish()
778
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000780 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530781 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800782 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700783 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000784 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
785 defer span.Finish()
786
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700787 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000788 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530789 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800790 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700791 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000792 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
793 defer span.Finish()
794
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700795 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000796 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 -0800797 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400799 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800800 }
801 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700802 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000803 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
804 defer span.Finish()
805
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000807 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700808 "intf-type": pktInd.IntfId,
809 "intf-id": pktInd.IntfId,
810 "gem-port-id": pktInd.GemportId,
811 "port-no": pktInd.PortNo,
812 "device-id": dh.device.Id,
813 })
814
815 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700817 "intf-type": pktInd.IntfId,
818 "intf-id": pktInd.IntfId,
819 "gem-port-id": pktInd.GemportId,
820 "port-no": pktInd.PortNo,
821 "packet": hex.EncodeToString(pktInd.Pkt),
822 "device-id": dh.device.Id,
823 })
824 }
825
David K. Bainbridge794735f2020-02-11 21:01:37 -0800826 go func() {
827 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400828 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800829 }
830 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000832 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
833 defer span.Finish()
834
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700835 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700836 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000838 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
839 defer span.Finish()
840
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700841 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700843 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000844 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
845 defer span.Finish()
846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000848 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
849 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530850 case *oop.Indication_OnuDisabledInd:
851 span, ctx := log.CreateChildSpan(ctx, "onu-disable-indication", log.Fields{"device-id": dh.device.Id})
852 defer span.Finish()
853 logger.Infow(ctx, "received onu-disable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
854 if err := dh.handleOnuDisableIndication(ctx, indication.GetOnuDisabledInd()); err != nil {
855 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
856 }
857 case *oop.Indication_OnuEnabledInd:
858 span, ctx := log.CreateChildSpan(ctx, "onu-enable-indication", log.Fields{"device-id": dh.device.Id})
859 defer span.Finish()
860 logger.Infow(ctx, "received onu-enable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
861 if err := dh.handleOnuEnableIndication(ctx, indication.GetOnuEnabledInd()); err != nil {
862 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
863 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700864 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530865}
866
nikesh.krishnanc8473432023-06-14 12:14:54 +0530867func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
868 onuInd := &oop.OnuIndication{
869 IntfId: intfID,
870 OnuId: onuID,
871 OperState: operState,
872 AdminState: adminState,
873 }
874 indication := &oop.Indication{
875 Data: &oop.Indication_OnuInd{
876 OnuInd: onuInd,
877 },
878 }
879 return indication
880}
881
882func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
883 onuAlarmInd := &oop.OnuAlarmIndication{
884 IntfId: intfID,
885 OnuId: onuID,
886 LosStatus: losStatus,
887 }
888 alarmInd := &oop.AlarmIndication{
889 Data: &oop.AlarmIndication_OnuAlarmInd{
890 OnuAlarmInd: onuAlarmInd,
891 },
892 }
893 return alarmInd
894}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530895
Akash Kankanala041a2122024-10-16 15:49:22 +0530896func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530897 ponlosAlarmInd := &oop.LosIndication{
898 IntfId: intfID,
899 Status: losStatus,
900 }
901 alarmInd := &oop.AlarmIndication{
902 Data: &oop.AlarmIndication_LosInd{
903 LosInd: ponlosAlarmInd,
904 },
905 }
906 return alarmInd
907}
Akash Kankanala041a2122024-10-16 15:49:22 +0530908
nikesh.krishnanc8473432023-06-14 12:14:54 +0530909func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
910 go func() {
911 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
912 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
913 }
914 }()
915
916 raisedTs := time.Now().Unix()
917 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
918}
919
920func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530921 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
922 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530923 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530924 return err
925 }
926 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530927 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
928 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
929 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
930
931 onuID := onuDeviceFromCore.ProxyAddress.OnuId
932 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
933 if err != nil {
934 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530935 } else {
936 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
937 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
938 switch {
939 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
940 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
941 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
942
943 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530944 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530945 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
946 raisedTs := time.Now().Unix()
947 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
948
949 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
950 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530951 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530952 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530953 return nil
954}
955
956func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
957 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
958 DeviceId: dh.device.Id,
959 PortType: voltha.Port_PON_OLT,
960 })
961 if err != nil {
962 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530963 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530964 }
965 for _, portFromCore := range portsFromCore.Items {
966 portNum := portFromCore.GetPortNo()
967 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
968 portOperStatusFromCore := portFromCore.OperStatus
969 portAdminStateFromCore := portFromCore.AdminState
970 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
971 if err != nil {
972 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
973 } else {
974 portLosFromOlt := ponPortFromOlt.GetLos()
975 portStateFromOlt := ponPortFromOlt.GetState()
976 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
977 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
978 "portStateFromOlt": portStateFromOlt.String(),
979 "portOperStatusFromCore": portOperStatusFromCore.String(),
980 "device-id": dh.device.Id,
981 "port": portNum})
982 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
983 raisedTs := time.Now().Unix()
984 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530985 }
986 switch {
987 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
988 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
989 "portStateFromOlt": portStateFromOlt.String(),
990 "portOperStatusFromCore": portOperStatusFromCore.String(),
991 "device-id": dh.device.Id,
992 "port": portNum})
993 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
994 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
995 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
996 "portStateFromOlt": portStateFromOlt.String(),
997 "portOperStatusFromCore": portOperStatusFromCore.String(),
998 "device-id": dh.device.Id,
999 "port": portNum})
1000 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
1001 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
1002 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
1003 "device-id": dh.device.Id,
1004 "port": portNum})
1005 default:
1006 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
1007 "portStateFromOlt": portStateFromOlt.String(),
1008 "portOperStatusFromCore": portOperStatusFromCore.String(),
1009 "device-id": dh.device.Id,
1010 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301011 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301012 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301013 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301014 return nil
1015}
1016
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301017// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301018func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +05301019 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +05301020 // Declare deviceStateFilter to be used later
1021 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +05301022 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001023 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +05301024 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301025 if err != nil {
1026 return fmt.Errorf("failed to get device from core: %w", err)
1027 }
1028 logger.Info(ctx, "Device state", log.Fields{
1029 "device-id": device.Id,
1030 "CurrOperStatus": device.OperStatus,
1031 "CurrConnStatus": device.ConnectStatus,
1032 })
1033 // Perform cleanup if the device's operational status is REBOOTED
1034 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
1035 // Log the device's operational status if it's REBOOTED
1036 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
1037 "device-id": device.Id,
1038 "OperStatus": device.OperStatus,
1039 })
1040 dh.lockDevice.RLock()
1041 // Stop the read indication only if it the routine is active
1042 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1043 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1044 // on next execution of the readIndication routine.
1045 if dh.isHeartbeatCheckActive {
1046 dh.stopHeartbeatCheck <- true
1047 }
1048 if dh.isReadIndicationRoutineActive {
1049 dh.stopIndications <- true
1050 }
bseenivaaa9165b2025-09-18 17:28:12 +05301051 if dh.isCollectorActive {
1052 dh.stopCollector <- true
1053 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301054 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +05301055 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301056 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
1057 return fmt.Errorf("cleanup device resources failed: %w", err)
1058 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301059 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301060 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1061 }
bseenivaaa9165b2025-09-18 17:28:12 +05301062 dh.collectorWaitGroup.Add(1)
1063 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301064 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301065 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +05301066 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
1067 // Log the device's operational status if it's RECONCILING
1068 logger.Info(ctx, "Device is being reconciled", log.Fields{
1069 "device-id": device.Id,
1070 "OperStatus": device.OperStatus,
1071 })
1072
1073 // Perform reconciliation steps
1074 err = dh.reconcileOnus(ctx)
1075 if err != nil {
1076 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1077 }
1078 err = dh.reconcilePonPorts(ctx)
1079 if err != nil {
1080 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301081 }
1082 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001083 // instantiate the mcast handler routines.
1084 for i := range dh.incomingMcastFlowOrGroup {
1085 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1086 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1087 if !dh.mcastHandlerRoutineActive[i] {
1088 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1089 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1090 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1091 // for incoming mcast flow/group to be processed serially.
1092 dh.mcastHandlerRoutineActive[i] = true
1093 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1094 }
1095 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301096 // Create DeviceStateFilter with the desired operational and connection statuses
1097 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001098 DeviceId: dh.device.Id,
1099 OperStatus: voltha.OperStatus_ACTIVE,
1100 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301101 }
1102 // Log DeviceStateFilter for debugging purposes
1103 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1104 "DeviceId": deviceStateFilter.DeviceId,
1105 "OperStatus": deviceStateFilter.OperStatus,
1106 "ConnStatus": deviceStateFilter.ConnStatus,
1107 })
1108 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301109 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001110 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001111 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001112
Akash Kankanala041a2122024-10-16 15:49:22 +05301113 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001114 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1115 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301116
1117 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1118 if err != nil {
1119 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1120 }
1121 dh.populateActivePorts(ctx, ports.Items)
1122 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1123 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1124 }
1125
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001126 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001127 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1128
Girish Gowdru0c588b22019-04-23 23:24:56 -04001129 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301130}
1131
1132// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301133func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001134 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001135
khenaidoo106c61a2021-08-11 18:05:46 -04001136 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001137 if err != nil || device == nil {
1138 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001139 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001140 }
1141
1142 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001143
Akash Kankanala041a2122024-10-16 15:49:22 +05301144 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001145 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001146 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001147 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001148 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001149
khenaidoodc2116e2021-10-19 17:33:19 -04001150 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001151 DeviceId: cloned.Id,
1152 OperStatus: cloned.OperStatus,
1153 ConnStatus: cloned.ConnectStatus,
1154 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001155 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001156 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001157
Akash Kankanala041a2122024-10-16 15:49:22 +05301158 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001159 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001160 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001161 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001162 }
1163 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001164 // Update onu state as down in onu adapter
1165 onuInd := oop.OnuIndication{}
1166 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001167
1168 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1169 if err != nil {
1170 return err
1171 }
1172 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001173 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001174 DeviceId: onuDevice.Id,
1175 OnuIndication: &onuInd,
1176 })
1177 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001178 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001179 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001180 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001181 "onu-indicator": onuInd,
1182 "device-type": onuDevice.Type,
1183 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301184 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001185 } else {
1186 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 -07001187 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001188 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001189 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001190 /* Discovered ONUs entries need to be cleared , since after OLT
1191 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301192 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001193 dh.lockDevice.Unlock()
1194
Neha Sharma96b7bf22020-06-15 10:37:32 +00001195 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001196 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301197}
1198
1199// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301200func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001201 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001202
1203 // if the connection is already available, close the previous connection (olt reboot case)
1204 if dh.clientCon != nil {
1205 if err = dh.clientCon.Close(); err != nil {
1206 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1207 } else {
1208 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1209 }
1210 }
1211
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301212 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Abhay Kumard3f18512025-12-09 07:51:12 +00001213 grpc_prometheus.EnableClientHandlingTimeHistogram()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001214 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001215 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1216 grpc.WithInsecure(),
1217 grpc.WithBlock(),
1218 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001219 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001220 grpc_prometheus.StreamClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001221 )),
1222 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001223 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001224 grpc_prometheus.UnaryClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001225 )))
1226
1227 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301228 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301229 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001230 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001231 }
Akash Sonif49299a2024-04-25 12:06:37 +05301232 //Setting oper and connection state to RECONCILING and conn state to reachable
1233 cgClient, err := dh.coreClient.GetCoreServiceClient()
1234 if err != nil {
1235 return err
1236 }
1237
1238 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1239 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1240 defer cancel()
1241 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1242 DeviceId: dh.device.Id,
1243 OperStatus: voltha.OperStatus_RECONCILING,
1244 ConnStatus: voltha.ConnectStatus_REACHABLE,
1245 }); err != nil {
1246 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1247 }
1248 // 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
1249 // locally cached copy of the device struct.
1250 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1251 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1252 }
1253
Girish Gowdru0c588b22019-04-23 23:24:56 -04001254 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301255}
1256
1257// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301258func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001259 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301260 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001261 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301262}
1263
1264// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301265func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301266 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001267 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001268
1269 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001270 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301271 if err != nil || device == nil {
1272 /*TODO: needs to handle error scenarios */
1273 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1274 }
1275 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001276 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001277
1278 cloned := proto.Clone(device).(*voltha.Device)
1279 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1280 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1281 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001282
khenaidoodc2116e2021-10-19 17:33:19 -04001283 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001284 DeviceId: cloned.Id,
1285 OperStatus: cloned.OperStatus,
1286 ConnStatus: cloned.ConnectStatus,
1287 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301288 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 -04001289 }
1290
Chaitrashree G S44124192019-08-07 20:21:36 -04001291 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
npujarec5762e2020-01-01 14:08:48 +05301292 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001293 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301294 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001295 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001296 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1297 // all the modules initialized and ready to handle incoming ONUs.
1298
Thomas Lee S985938d2020-05-04 11:40:41 +05301299 err = dh.initializeDeviceHandlerModules(ctx)
1300 if err != nil {
1301 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 -04001302 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001303
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001304 go startHeartbeatCheck(ctx, dh)
1305
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001306 return nil
1307 }
1308
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001309 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301310 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001311 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301312
Neha Sharma96b7bf22020-06-15 10:37:32 +00001313 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001314
1315 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001316 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001317 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001318
1319 go startHeartbeatCheck(ctx, dh)
1320
cuilin20187b2a8c32019-03-26 19:52:28 -07001321 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301322}
1323
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001324func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001325 var err error
1326 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001327
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001328 if dh.flowMgr != nil {
1329 dh.StopAllFlowRoutines(ctx)
1330 }
1331
1332 dh.CloseKVClient(ctx)
1333
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001334 if err != nil {
1335 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1336 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001337 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1338 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301339 // If collector go routine is active, wait for it to stop
1340 dh.lockDevice.RLock()
1341 if dh.isCollectorActive {
1342 dh.lockDevice.RUnlock()
1343 dh.collectorWaitGroup.Wait()
1344 } else {
1345 dh.lockDevice.RUnlock()
1346 }
yasin saplid0566272021-12-21 09:10:30 +00001347 // +1 is for NNI
1348 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1349 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001350 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001351 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1352 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1353 // There is only one NNI manager since multiple NNI is not supported for now
1354 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001355 // Instantiate resource manager
1356 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 -07001357 return olterrors.ErrResourceManagerInstantiating
1358 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001359 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001360 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1361 // the KV store to manage mcast group data. Provide the first instance (0th index)
1362 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1363 return olterrors.ErrGroupManagerInstantiating
1364 }
yasin saplid0566272021-12-21 09:10:30 +00001365 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001366 // Instantiate flow manager
1367 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301368 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001369 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1370 } else {
1371 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001372 }
1373 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001374 /* TODO: Instantiate Alarm , stats , BW managers */
1375 /* Instantiating Event Manager to handle Alarms and KPIs */
1376 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1377
1378 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001379 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001380
1381 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001382}
1383
Neha Sharma96b7bf22020-06-15 10:37:32 +00001384func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001385 var err error
1386 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301387 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001388
Neha Sharma8f4e4322020-08-06 10:51:53 +00001389 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001390
1391 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001392 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001393 }
1394 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001395 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001396 }
1397
Neha Sharma96b7bf22020-06-15 10:37:32 +00001398 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001399 dh.device.Root = true
1400 dh.device.Vendor = deviceInfo.Vendor
1401 dh.device.Model = deviceInfo.Model
1402 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1403 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1404 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1405
1406 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001407 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001408 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301409 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001410 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001411 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001412 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001413 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001414 dh.device.MacAddress = genmac
1415 } else {
1416 dh.device.MacAddress = deviceInfo.DeviceId
1417 }
1418
1419 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001420 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001422 }
1423
1424 return deviceInfo, nil
1425}
1426
Neha Sharma96b7bf22020-06-15 10:37:32 +00001427func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301428 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001429
1430 defer func() {
1431 dh.lockDevice.Lock()
1432 dh.isCollectorActive = false
1433 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301434 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001435 }()
1436
1437 dh.lockDevice.Lock()
1438 dh.isCollectorActive = true
1439 dh.lockDevice.Unlock()
1440
Naga Manjunath7615e552019-10-11 22:35:47 +05301441 for {
1442 select {
1443 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301444 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301445 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001446 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001447
khenaidoo106c61a2021-08-11 18:05:46 -04001448 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001449 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001450 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001451 continue
1452 }
khenaidoo106c61a2021-08-11 18:05:46 -04001453 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301454 // NNI Stats
1455 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001456 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301457 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001458 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001459 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001460 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301461 }
1462 // PON Stats
1463 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001464 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301465 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1466 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001467 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001468 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301469 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001470 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001471
yasin sapli9e4c5092022-02-01 13:52:33 +00001472 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001473 if len(onuGemInfoLst) > 0 {
1474 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001475 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001476 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301477 }
1478 }
1479 }
1480}
1481
Mahir Gunyela2e68702022-12-07 00:00:42 -08001482// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301483func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001484 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001485 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301486 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301487
1488 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001489 cgClient, err := dh.coreClient.GetCoreServiceClient()
1490 if err != nil {
1491 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1492 return
1493 }
1494
1495 // Now, set the initial PM configuration for that device
1496 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001497 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301498 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301499}
1500
Mahir Gunyela2e68702022-12-07 00:00:42 -08001501// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001502func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1503 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001504 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301505 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001506 HwDesc: "open_pon",
1507 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001508 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001509 },
1510 SwitchFeatures: &of.OfpSwitchFeatures{
1511 NBuffers: 256,
1512 NTables: 2,
1513 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1514 of.OfpCapabilities_OFPC_TABLE_STATS |
1515 of.OfpCapabilities_OFPC_PORT_STATS |
1516 of.OfpCapabilities_OFPC_GROUP_STATS),
1517 },
1518 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301519}
1520
khenaidoo106c61a2021-08-11 18:05:46 -04001521// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001522func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001523 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001524 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001525 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001526 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001527 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1528 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()
1529 }
khenaidoo106c61a2021-08-11 18:05:46 -04001530 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001531}
1532
Neha Sharma96b7bf22020-06-15 10:37:32 +00001533func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001534 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 -07001535 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536 var deviceID string
1537 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001538 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001539
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001540 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001541 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001542 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 -07001543 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1544 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001545
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001546 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301547
1548 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001549 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 -07001550 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001551
khenaidoodc2116e2021-10-19 17:33:19 -04001552 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001553 ParentId: dh.device.Id,
1554 OnuId: omciInd.OnuId,
1555 ParentPortNo: ponPort,
1556 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001557 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301558 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001559 "intf-id": omciInd.IntfId,
1560 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001561 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 deviceType = onuDevice.Type
1563 deviceID = onuDevice.Id
1564 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001565 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301566 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001567 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001568 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301569 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 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 +05301571 deviceType = onuInCache.(*OnuDevice).deviceType
1572 deviceID = onuInCache.(*OnuDevice).deviceID
1573 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001574 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001575 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001576
khenaidoodc2116e2021-10-19 17:33:19 -04001577 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001578 ParentDeviceId: proxyDeviceID,
1579 ChildDeviceId: deviceID,
1580 Message: omciInd.Pkt,
1581 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301582 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001583 "source": dh.openOLT.config.AdapterEndpoint,
1584 "device-type": deviceType,
1585 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001586 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001587 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001588 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001589 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301590}
1591
khenaidoo106c61a2021-08-11 18:05:46 -04001592// //ProcessInterAdapterMessage sends the proxied messages to the target device
1593// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1594// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001595// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001596// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001597// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001598// return dh.handleInterAdapterOmciMsg(ctx, msg)
1599// }
1600// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1601// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001602
kesavandb9f54fd2021-11-25 20:08:04 +05301603// ProxyOmciRequests sends the proxied OMCI message to the target device
1604func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301605 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1606 return status.Error(codes.Unavailable, "OLT unreachable")
1607 }
kesavandb9f54fd2021-11-25 20:08:04 +05301608 if omciMsgs.GetProxyAddress() == nil {
1609 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1610 if err != nil {
1611 return olterrors.NewErrNotFound("onu", log.Fields{
1612 "parent-device-id": dh.device.Id,
1613 "child-device-id": omciMsgs.ChildDeviceId}, err)
1614 }
1615 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1616 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1617 return olterrors.NewErrCommunication("send-failed", log.Fields{
1618 "parent-device-id": dh.device.Id,
1619 "child-device-id": omciMsgs.ChildDeviceId}, err)
1620 }
1621 } else {
1622 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1623 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1624 return olterrors.NewErrCommunication("send-failed", log.Fields{
1625 "parent-device-id": dh.device.Id,
1626 "child-device-id": omciMsgs.ChildDeviceId}, err)
1627 }
1628 }
1629 return nil
1630}
1631
1632func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1633 var intfID uint32
1634 var onuID uint32
1635 var connectStatus common.ConnectStatus_Types
1636 if onuDevice != nil {
1637 intfID = onuDevice.ProxyAddress.GetChannelId()
1638 onuID = onuDevice.ProxyAddress.GetOnuId()
1639 connectStatus = onuDevice.ConnectStatus
1640 } else {
1641 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1642 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1643 connectStatus = omciMsgs.GetConnectStatus()
1644 }
1645 if connectStatus != voltha.ConnectStatus_REACHABLE {
1646 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1647
1648 return olterrors.NewErrCommunication("unreachable", log.Fields{
1649 "intf-id": intfID,
1650 "onu-id": onuID}, nil)
1651 }
1652
1653 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1654 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1655
1656 onuSecOmciMsgList := omciMsgs.GetMessages()
1657
1658 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301659 var omciMessage *oop.OmciMsg
1660 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1661 hex.Encode(hexPkt, onuSecOmciMsg)
1662 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1663
1664 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1665 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1666 //https://jira.opencord.org/browse/VOL-4604
1667 transid := extractOmciTransactionID(onuSecOmciMsg)
1668 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1669 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1670
1671 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1672 if err != nil {
1673 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1674 "intf-id": intfID,
1675 "onu-id": onuID,
1676 "message": omciMessage}, err)
1677 }
1678 }
1679 return nil
1680}
1681
khenaidoo106c61a2021-08-11 18:05:46 -04001682// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001683func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001684 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 -07001685
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301686 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1687 return status.Error(codes.Unavailable, "OLT unreachable")
1688 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001689 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001690 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001691 if err != nil {
1692 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001693 "parent-device-id": dh.device.Id,
1694 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001695 }
khenaidoo106c61a2021-08-11 18:05:46 -04001696 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1697 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001698 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001699 "parent-device-id": dh.device.Id,
1700 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001701 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001702 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001703 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1704 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001705 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001706 "parent-device-id": dh.device.Id,
1707 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001708 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001709 }
1710 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301711}
1712
khenaidoodc2116e2021-10-19 17:33:19 -04001713func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001714 var intfID uint32
1715 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001716 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001717 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001718 intfID = onuDevice.ProxyAddress.GetChannelId()
1719 onuID = onuDevice.ProxyAddress.GetOnuId()
1720 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001721 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001722 intfID = omciMsg.GetProxyAddress().GetChannelId()
1723 onuID = omciMsg.GetProxyAddress().GetOnuId()
1724 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001725 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001726 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001727 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 -08001728
Thomas Lee S94109f12020-03-03 16:39:29 +05301729 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001730 "intf-id": intfID,
1731 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001732 }
1733
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001734 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1735 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301736 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001737 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001738 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1739 hex.Encode(hexPkt, omciMsg.Message)
1740 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1741
1742 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1743 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1744 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001746 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001747
Neha Sharma8f4e4322020-08-06 10:51:53 +00001748 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001749 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301750 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001751 "intf-id": intfID,
1752 "onu-id": onuID,
1753 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001754 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001755 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001756}
1757
David K. Bainbridge794735f2020-02-11 21:01:37 -08001758func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301759 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 +00001760 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001761 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001762 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001763 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301764 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301765 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001766 st, _ := status.FromError(err)
1767 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001768 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 -04001769 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301770 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001771 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001772 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001773 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001774 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001775 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001776}
1777
Mahir Gunyela2e68702022-12-07 00:00:42 -08001778// getChildDevice function can be used in general to get child device, if not found in cache the function will
1779// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301780func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1781 var InCacheOnuDev *OnuDevice
1782 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1783 if onuInCache.(*OnuDevice).serialNumber == sn {
1784 InCacheOnuDev = onuInCache.(*OnuDevice)
1785 return false
1786 }
1787 return true
1788 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301789 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301790 if InCacheOnuDev != nil {
1791 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1792 return InCacheOnuDev
1793 }
1794 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1795 ParentId: dh.device.Id,
1796 SerialNumber: sn,
1797 ParentPortNo: parentPortNo,
1798 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301799 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301800 if onuDevice == nil {
1801 return nil
1802 }
1803 onuID := onuDevice.ProxyAddress.OnuId
1804 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1805 onuKey := dh.formOnuKey(intfID, onuID)
1806
1807 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1808 dh.onus.Store(onuKey, onuDev)
1809 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1810 return onuDev
1811}
1812
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301813// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1814// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301815func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001816 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301817 // 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 +05301818 // 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 +05301819 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1820 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1821 ParentId: dh.device.Id,
1822 SerialNumber: sn,
1823 ParentPortNo: parentPortNo,
1824 })
1825 if onuDevice != nil {
1826 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1827 return true, nil
1828 }
1829 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1830
1831 return false, nil
1832 } else {
1833 tpInstExists := false
1834 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301835 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1836 if onuDev != nil {
1837 var onuGemInfo *rsrcMgr.OnuGemInfo
1838 var err error
1839 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1840 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1841 return false, err
1842 }
1843 if onuGemInfo != nil {
1844 for _, uni := range onuGemInfo.UniPorts {
1845 uniID := plt.UniIDFromPortNum(uni)
1846 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1847 if len(tpIDs) != 0 {
1848 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1849 tpInstExists = true
1850 break
1851 }
1852 }
1853 }
1854 }
1855 return tpInstExists, nil
1856 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301857}
1858
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001859// processDiscONULOSClear clears the LOS Alarm if it's needed
1860func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301861 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001862 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301863
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001864 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1865 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1866 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1867 OnuLosRaise event sent for it */
1868 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1869 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1870 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1871 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1872 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1873 "currentIntfId": onuDiscInd.GetIntfId()})
1874 // TODO:: Should we need to ignore raising OnuLosClear event
1875 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301876 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001877 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1878 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1879 alarmInd.LosStatus = statusCheckOff
1880 go func() {
1881 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1882 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1883 }
1884 }()
1885 // stop iterating
1886 return false
1887 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301888 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001889 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301890}
1891
bseeniva43b5a912025-06-05 12:48:15 +05301892func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1893 if err != nil || tpInstExists {
1894 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1895 } else {
1896 // once the function completes set the value to false so that
1897 // we know the processing has inProcess.
1898 // Note that this is done after checking if we are already processing
1899 // to avoid changing the value from a different thread
1900 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1901 dh.discOnus.Store(sn, false)
1902 }
1903}
1904
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301905func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301906 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301907 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301908
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301909 channelID := onuDiscInd.GetIntfId()
1910 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1911
1912 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301913 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301914 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301915 }()
1916
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301917 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1918
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301919 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1920 if !dh.cfg.ForceOnuDiscIndProcessing {
1921 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1922 if error != nil {
1923 return error
1924 }
1925 if tpInstExists {
1926 // ignore the discovery if tpinstance is present.
1927 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1928 return nil
1929 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001930 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001931 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1932
1933 // if the ONU existed, handle the LOS Alarm
1934 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001935 if inProcess.(bool) {
1936 // if we're currently processing the ONU on a different thread, do nothing
1937 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1938 return nil
1939 }
1940 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1941 // then continue processing it
1942 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1943
1944 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001945 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301946 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001947 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001948
1949 // check the ONU is already know to the OLT
1950 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301951 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001952 ParentId: dh.device.Id,
1953 SerialNumber: sn,
1954 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001955
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301956 if error != nil {
1957 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1958 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001959 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 -08001960 switch e.Code() {
1961 case codes.Internal:
1962 // this probably means NOT FOUND, so just create a new device
1963 onuDevice = nil
1964 case codes.DeadlineExceeded:
1965 // if the call times out, cleanup and exit
1966 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301967 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1968 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001969 }
1970 }
1971 }
1972
1973 if onuDevice == nil {
1974 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001976 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001977 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301978 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001979 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001980
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301981 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001982 // if we can't create an ID in resource manager,
1983 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001984 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301985
1986 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001987 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301988 "serial-number": sn}, error)
1989 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001990 }
1991
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301992 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001993 ParentId: dh.device.Id,
1994 ParentPortNo: parentPortNo,
1995 ChannelId: channelID,
1996 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1997 SerialNumber: sn,
1998 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301999 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002000 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00002001 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 +05302002
2003 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002004 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302005 "serial-number": sn}, error)
2006 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002007 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302008 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 +05302009 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2010 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2011 "onu-id": onuID,
2012 "device-id": dh.device.Id,
2013 "serial-number": sn}, error)
2014 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002015 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002016 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302017 log.Fields{"onuDevice": onuDevice,
2018 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002019 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302020 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002021 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002022
khenaidoo106c61a2021-08-11 18:05:46 -04002023 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2024 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302025 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002026 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302027 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302028 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2029 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002030 }
2031
Matteo Scandolo945e4012019-12-12 14:16:11 -08002032 // we can now use the existing ONU Id
2033 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302034 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002035 //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 +00002036 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002037 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302038 "intfId": onuDiscInd.GetIntfId(),
2039 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002040 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002041
khenaidoo106c61a2021-08-11 18:05:46 -04002042 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302043 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002044 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302045 log.Fields{"onu": onuDev,
2046 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002047
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302048 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002049 DeviceId: onuDevice.Id,
2050 ParentDeviceId: dh.device.Id,
2051 OperStatus: common.OperStatus_DISCOVERED,
2052 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302053 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302054 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002055 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302056 "serial-number": sn}, error)
2057 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002058 }
khenaidoo106c61a2021-08-11 18:05:46 -04002059
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302061 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302062 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002063 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302064 "serial-number": sn}, error)
2065 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002066 }
2067 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002068}
2069
Mahir Gunyelb0046752021-02-26 13:51:05 -08002070func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002071 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002072 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002073 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002074 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002075 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302076 log.Fields{"onuId": onuInd.OnuId,
2077 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302078 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002079 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002080 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002081 errFields := log.Fields{"device-id": dh.device.Id}
2082
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302083 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302084 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002085 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002086 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002087 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002088 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302089 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002090 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002091 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002092 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002093 errFields["onu-id"] = onuInd.OnuId
2094 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002095 }
khenaidoodc2116e2021-10-19 17:33:19 -04002096 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002097 ParentId: dh.device.Id,
2098 SerialNumber: serialNumber,
2099 OnuId: onuInd.OnuId,
2100 ParentPortNo: ponPort,
2101 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002102 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002103
David K. Bainbridge794735f2020-02-11 21:01:37 -08002104 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002105 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002106 }
2107
David K. Bainbridge794735f2020-02-11 21:01:37 -08002108 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002109 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002110 "previousIntfId": onuDevice.ParentPortNo,
2111 "currentIntfId": ponPort})
2112 }
2113
2114 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302116 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2117 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302118 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002119 }
2120 if !foundInCache {
2121 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002122 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 -08002123 }
kesavand7cf3a052020-08-28 12:49:18 +05302124 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002125 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002126 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302127 }
2128 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002129 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002130 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002131 }
2132 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002133}
2134
Neha Sharma96b7bf22020-06-15 10:37:32 +00002135func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002136 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 -07002137 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2138 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2139 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2140 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002141 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002142 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2143 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002145 onuInd.OperState = "down"
2146 }
2147 }
2148
David K. Bainbridge794735f2020-02-11 21:01:37 -08002149 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002150 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151 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 -04002152
khenaidoodc2116e2021-10-19 17:33:19 -04002153 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002154 DeviceId: onuDevice.Id,
2155 OnuIndication: onuInd,
2156 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002157 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302158 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002159 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002160 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002161 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002162 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002163 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002164 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002165 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002166 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002167 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002168}
2169
cuilin20187b2a8c32019-03-26 19:52:28 -07002170func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2171 if serialNum != nil {
2172 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002173 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002174 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002175}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002176func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2177 decodedStr, err := hex.DecodeString(serialNum[4:])
2178 if err != nil {
2179 return nil, err
2180 }
2181 return &oop.SerialNumber{
2182 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002183 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002184 }, nil
2185}
cuilin20187b2a8c32019-03-26 19:52:28 -07002186
2187func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002188 if len(vendorSpecific) > 3 {
2189 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2190 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2191 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2192 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2193 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2194 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2195 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2196 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2197 return tmp
2198 }
2199 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002200}
2201
Mahir Gunyela2e68702022-12-07 00:00:42 -08002202// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002203func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302204 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002205}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002206
Mahir Gunyela2e68702022-12-07 00:00:42 -08002207// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002208func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2209 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302210 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002211 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302212 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002213
khenaidoodc2116e2021-10-19 17:33:19 -04002214 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002215 ParentId: dh.device.Id,
2216 OnuId: onuID,
2217 ParentPortNo: parentPort,
2218 })
2219
Girish Gowdru0c588b22019-04-23 23:24:56 -04002220 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002221 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002222 "intf-id": parentPort,
2223 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002224 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002225 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 -08002226 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302227}
2228
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002229// SendPacketInToCore sends packet-in to core
2230// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2231// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002232func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002233 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002234 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002235 "port": logicalPort,
2236 "packet": hex.EncodeToString(packetPayload),
2237 "device-id": dh.device.Id,
2238 })
2239 }
khenaidoo106c61a2021-08-11 18:05:46 -04002240
khenaidoodc2116e2021-10-19 17:33:19 -04002241 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002242 DeviceId: dh.device.Id,
2243 Port: logicalPort,
2244 Packet: packetPayload,
2245 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302246 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002247 "source": "adapter",
2248 "destination": "core",
2249 "device-id": dh.device.Id,
2250 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002251 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002252 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002253 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002254 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002255 "packet": hex.EncodeToString(packetPayload),
2256 "device-id": dh.device.Id,
2257 })
2258 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002259 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002260}
2261
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002262// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002263func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002265
2266 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2267 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002269 }
2270
Kent Hagermane6ff1012020-07-14 15:07:53 -04002271 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002272 metrics := dh.metrics.GetSubscriberMetrics()
2273 for _, m := range pmConfigs.Metrics {
2274 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002275 }
2276 }
2277}
2278
khenaidoodc2116e2021-10-19 17:33:19 -04002279func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002280 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002281 var errorsList []error
2282
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002283 if dh.getDeviceDeletionInProgressFlag() {
2284 // The device itself is going to be reset as part of deletion. So nothing to be done.
2285 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2286 return nil
2287 }
2288
Girish Gowdru0c588b22019-04-23 23:24:56 -04002289 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002290 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302291 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002292
Neha Sharma96b7bf22020-06-15 10:37:32 +00002293 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302294 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002295 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302296 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002297 if flow_utils.HasGroup(flow) {
2298 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2299 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002300 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2301 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2302 } else {
2303 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2304 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002305 }
Girish Gowdracefae192020-03-19 18:14:10 -07002306 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002307 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302308 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002309 logger.Warnw(ctx, "flow-to-remove-not-found",
2310 log.Fields{
2311 "ponIf": intfID,
2312 "flowToRemove": flow,
2313 "error": err,
2314 })
2315 } else {
2316 errorsList = append(errorsList, err)
2317 }
Girish Gowdracefae192020-03-19 18:14:10 -07002318 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002319 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302320
2321 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302322 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302324 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002325 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302326 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002327 if flow_utils.HasGroup(flow) {
2328 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2329 } else {
yasin saplid0566272021-12-21 09:10:30 +00002330 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002331 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2332 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2333 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2334 } else {
yasin saplid0566272021-12-21 09:10:30 +00002335 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002336 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002337 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002338 if err != nil {
2339 errorsList = append(errorsList, err)
2340 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302341 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002342 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002343
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002344 return errorsList
2345}
2346
2347func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2348 var err error
2349 var errorsList []error
2350
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002351 if dh.getDeviceDeletionInProgressFlag() {
2352 // The device itself is going to be reset as part of deletion. So nothing to be done.
2353 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2354 return nil
2355 }
2356
Girish Gowdracefae192020-03-19 18:14:10 -07002357 // 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 +00002358 if groups != nil {
2359 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002360 // err = dh.groupMgr.AddGroup(ctx, group)
2361 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002362 if err != nil {
2363 errorsList = append(errorsList, err)
2364 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002365 }
2366 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002367 // err = dh.groupMgr.ModifyGroup(ctx, group)
2368 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002369 if err != nil {
2370 errorsList = append(errorsList, err)
2371 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002372 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002373 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002374 // err = dh.groupMgr.DeleteGroup(ctx, group)
2375 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002376 if err != nil {
2377 errorsList = append(errorsList, err)
2378 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002379 }
2380 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002381
2382 return errorsList
2383}
2384
Mahir Gunyela2e68702022-12-07 00:00:42 -08002385// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002386func (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 -07002387 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002388
2389 if dh.getDeviceDeletionInProgressFlag() {
2390 // The device itself is going to be reset as part of deletion. So nothing to be done.
2391 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2392 return nil
2393 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302394 if dh.transitionMap.currentDeviceState != deviceStateUp {
2395 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2396 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2397 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002398 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2399 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2400 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002401 if len(errorsList) > 0 {
2402 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2403 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002404 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002405 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302406}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002407
Mahir Gunyela2e68702022-12-07 00:00:42 -08002408// DisableDevice disables the given device
2409// It marks the following for the given device:
2410// Device-Handler Admin-State : down
2411// Device Port-State: UNKNOWN
2412// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002414 /* On device disable ,admin state update has to be done prior sending request to agent since
2415 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002416 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002417 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002418 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002419 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002420 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002421 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002422 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002423 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002424 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002425 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302426
2427 dh.discOnus = sync.Map{}
2428 dh.onus = sync.Map{}
2429
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002430 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302431 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002432 if dh.isCollectorActive {
2433 dh.stopCollector <- true
2434 }
2435 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302436
Neha Sharma96b7bf22020-06-15 10:37:32 +00002437 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002438 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302439 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302440 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002441
kdarapu1afeceb2020-02-12 01:38:09 -05002442 // 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 -04002443 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002444 DeviceId: cloned.Id,
2445 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2446 OperStatus: voltha.OperStatus_UNKNOWN,
2447 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002448 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002449 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002450 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002451 return nil
2452}
2453
Neha Sharma96b7bf22020-06-15 10:37:32 +00002454func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002455 // Update onu state as unreachable in onu adapter
2456 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302457 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002458
Akash Kankanala041a2122024-10-16 15:49:22 +05302459 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002460 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002461 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002462 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 -04002463 }
2464 if onuDevices != nil {
2465 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002466 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002467 DeviceId: onuDevice.Id,
2468 OnuIndication: &onuInd,
2469 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002470 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002471 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002472 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002473 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002474 }
2475 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002476}
2477
Mahir Gunyela2e68702022-12-07 00:00:42 -08002478// ReenableDevice re-enables the olt device after disable
2479// It marks the following for the given device:
2480// Device-Handler Admin-State : up
2481// Device Port-State: ACTIVE
2482// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302484 if dh.Client != nil {
2485 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2486 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2487 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2488 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302489 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302490 } else {
2491 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 +05302492 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002493 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002494
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002495 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002496 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002497 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002498 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002499 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2500 } else {
2501 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2502 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2503 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002504 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002505 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302506 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002507 device.OperStatus = voltha.OperStatus_ACTIVE
2508 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302509 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002510 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002511 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002512 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002513
khenaidoodc2116e2021-10-19 17:33:19 -04002514 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002515 DeviceId: device.Id,
2516 OperStatus: device.OperStatus,
2517 ConnStatus: device.ConnectStatus,
2518 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302519 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002520 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002521 "connect-status": device.ConnectStatus,
2522 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002523 }
kesavand39e0aa32020-01-28 20:58:50 -05002524
Neha Sharma96b7bf22020-06-15 10:37:32 +00002525 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002526
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002527 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002528}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002529
npujarec5762e2020-01-01 14:08:48 +05302530func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002531 var uniID uint32
2532 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002533 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302534 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002535 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002536 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002537 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002538 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2539 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2540 } else {
2541 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2542 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002543 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002544 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002545 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002546 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002547 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002548 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002549 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002550 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002551 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002552 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002553 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002554 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002555 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002556 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002557 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002558 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302559 }
yasin saplibddc2d72022-02-08 13:10:17 +00002560 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2561 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002562 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002563 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302564 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002565 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002566 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002567 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 -03002568 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002569 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002570 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002571 if len(errs) > 0 {
2572 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2573 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2574 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002575 return nil
2576}
2577
Devmalya Paul495b94a2019-08-27 19:42:00 -04002578// 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 +05302579func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002580 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002581 /* Clear the KV store data associated with the all the UNI ports
2582 This clears up flow data and also resource map data for various
2583 other pon resources like alloc_id and gemport_id
2584 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002585
2586 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002587 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002588
Himani Chawla49a5d562020-11-25 11:53:44 +05302589 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002590 // Stop the Stats collector
2591 if dh.isCollectorActive {
2592 dh.stopCollector <- true
2593 }
2594 // stop the heartbeat check routine
2595 if dh.isHeartbeatCheckActive {
2596 dh.stopHeartbeatCheck <- true
2597 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302598 // Stop the read indication only if it the routine is active
2599 if dh.isReadIndicationRoutineActive {
2600 dh.stopIndications <- true
2601 }
2602 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302603
2604 err := dh.cleanupDeviceResources(ctx)
2605 if err != nil {
2606 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2607 } else {
2608 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2609 }
2610
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002611 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302612 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002613 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302614 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002615 go func() {
2616 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302617 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2618 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002619 }
2620 }()
2621 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002622 }
2623 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002624 // There is no need to update the core about operation status and connection status of the OLT.
2625 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2626 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2627 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002628
khenaidoo7eb2d672021-10-22 19:08:50 -04002629 // Stop the adapter grpc clients for that parent device
2630 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002631 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002632}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002633
2634// StopAllFlowRoutines stops all flow routines
2635func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2636 var wg sync.WaitGroup
2637 wg.Add(1) // for the mcast routine below to finish
2638 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2639 for _, flMgr := range dh.flowMgr {
2640 if flMgr != nil {
2641 wg.Add(1) // for the flow handler routine below to finish
2642 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2643 }
2644 }
2645 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2646 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2647 } else {
2648 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2649 }
2650}
2651
Gustavo Silva41af9122022-10-11 11:05:13 -03002652func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2653 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002654 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302655 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002656 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002657 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002658 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002659 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002660 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2661 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302662 }
2663 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002664 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2665 errs = append(errs, err)
2666 }
2667 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2668 errs = append(errs, err)
2669 }
2670 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2671 errs = append(errs, err)
2672 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002673 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002674 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002675 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002676 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002677 }
2678 // Clean up NNI manager's data
2679 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2680 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002681 }
A R Karthick1f85b802019-10-11 05:06:05 +00002682
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002683 dh.CloseKVClient(ctx)
2684
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002685 // Take one final sweep at cleaning up KV store for the OLT device
2686 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002687 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2688 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002689 }
2690
Devmalya Paul495b94a2019-08-27 19:42:00 -04002691 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302692 dh.onus.Range(func(key interface{}, value interface{}) bool {
2693 dh.onus.Delete(key)
2694 return true
2695 })
2696
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002697 /*Delete discovered ONU map for the device*/
2698 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2699 dh.discOnus.Delete(key)
2700 return true
2701 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002702 if len(errs) > 0 {
2703 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2704 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2705 }
2706 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002707}
2708
Mahir Gunyela2e68702022-12-07 00:00:42 -08002709// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002710func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302711 if dh.Client != nil {
2712 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2713 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2714 }
2715 } else {
2716 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 -04002717 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302718
Neha Sharma96b7bf22020-06-15 10:37:32 +00002719 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002720 return nil
2721}
2722
David K. Bainbridge794735f2020-02-11 21:01:37 -08002723func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002724 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002725 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002726 "packet-indication": *packetIn,
2727 "device-id": dh.device.Id,
2728 "packet": hex.EncodeToString(packetIn.Pkt),
2729 })
2730 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002731 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2732 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2733 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002734 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002735 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002736 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002737 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002738 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002739 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002740 "logical-port-num": logicalPortNum,
2741 "device-id": dh.device.Id,
2742 "packet": hex.EncodeToString(packetIn.Pkt),
2743 })
2744 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002745
khenaidoodc2116e2021-10-19 17:33:19 -04002746 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002747 DeviceId: dh.device.Id,
2748 Port: logicalPortNum,
2749 Packet: packetIn.Pkt,
2750 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302751 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002752 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302753 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002754 "device-id": dh.device.Id,
2755 "packet": hex.EncodeToString(packetIn.Pkt),
2756 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002757 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002758
Matteo Scandolo92186242020-06-12 10:54:18 -07002759 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002761 "packet": hex.EncodeToString(packetIn.Pkt),
2762 "device-id": dh.device.Id,
2763 })
2764 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002765 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002766}
2767
Mahir Gunyela2e68702022-12-07 00:00:42 -08002768// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2769func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2770 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2771 if err != nil {
2772 return olterrors.NewErrInvalidValue(log.Fields{
2773 "egress-nni-port": egressPortNo,
2774 "device-id": dh.device.Id,
2775 }, err)
2776 }
2777 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2778
2779 if logger.V(log.DebugLevel) {
2780 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2781 "uplink-pkt": uplinkPkt,
2782 "packet": hex.EncodeToString(packet.Data),
2783 "device-id": dh.device.Id,
2784 })
2785 }
2786
2787 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2788 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2789 "packet": hex.EncodeToString(packet.Data),
2790 "device-id": dh.device.Id,
2791 }, err)
2792 }
2793 return nil
2794}
2795
2796// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2797func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2798 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2799 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2800 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2801 // Do not packet-out lldp packets on uni port.
2802 // ONOS has no clue about uni/nni ports, it just packets out on all
2803 // available ports on the Logical Switch. It should not be interested
2804 // in the UNI links.
2805 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2806 "device-id": dh.device.Id,
2807 })
2808 return nil
2809 }
2810 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2811 if innerEthType == 0x8100 {
2812 // q-in-q 802.1ad or 802.1q double tagged packet.
2813 // slice out the outer tag.
2814 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2815 if logger.V(log.DebugLevel) {
2816 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2817 "packet-data": hex.EncodeToString(packet.Data),
2818 "device-id": dh.device.Id,
2819 })
2820 }
2821 }
2822 }
2823 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2824 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2825 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2826 var gemPortID uint32
2827 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2828 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2829 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2830 }
2831 if err != nil {
2832 // In this case the openolt agent will receive the gemPortID as 0.
2833 // The agent tries to retrieve the gemPortID in this case.
2834 // This may not always succeed at the agent and packetOut may fail.
2835 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2836 "intf-id": intfID,
2837 "onu-id": onuID,
2838 "uni-id": uniID,
2839 "packet": hex.EncodeToString(packet.Data),
2840 "device-id": dh.device.Id,
2841 "error": err,
2842 })
2843 }
2844
2845 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2846 if logger.V(log.DebugLevel) {
2847 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2848 "egress-port-no": egressPortNo,
2849 "intf-id": intfID,
2850 "onu-id": onuID,
2851 "uni-id": uniID,
2852 "gem-port-id": gemPortID,
2853 "packet": hex.EncodeToString(packet.Data),
2854 "device-id": dh.device.Id,
2855 })
2856 }
2857
2858 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2859 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2860 "source": "adapter",
2861 "destination": "onu",
2862 "egress-port-number": egressPortNo,
2863 "intf-id": intfID,
2864 "oni-id": onuID,
2865 "uni-id": uniID,
2866 "gem-port-id": gemPortID,
2867 "packet": hex.EncodeToString(packet.Data),
2868 "device-id": dh.device.Id,
2869 }, err)
2870 }
2871 return nil
2872}
2873
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002874// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002875func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002876 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002877 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002878 "device-id": dh.device.Id,
2879 "egress-port-no": egressPortNo,
2880 "pkt-length": len(packet.Data),
2881 "packet": hex.EncodeToString(packet.Data),
2882 })
2883 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002884
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002885 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002886 var err error
mgouda86543582025-10-29 20:58:16 +05302887 switch egressPortType {
2888 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002889 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302890 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002891 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302892 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002893 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302894 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002895 "egressPortType": egressPortType,
2896 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302897 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002898 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002899 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002900 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002901}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002902
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002903func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2904 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002905}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302906
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002907func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002908 defer func() {
2909 dh.lockDevice.Lock()
2910 dh.isHeartbeatCheckActive = false
2911 dh.lockDevice.Unlock()
2912 }()
2913
2914 dh.lockDevice.Lock()
2915 dh.isHeartbeatCheckActive = true
2916 dh.lockDevice.Unlock()
2917
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302918 // start the heartbeat check towards the OLT.
2919 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302920 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302921
2922 for {
2923 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2924 select {
2925 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002926 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002927 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002928 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302929 if timerCheck == nil {
2930 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002931 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302932 }
2933 } else {
2934 if timerCheck != nil {
2935 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002936 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302937 }
2938 timerCheck = nil
2939 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302940 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2941 if dh.heartbeatSignature == 0 {
2942 // First time the signature will be 0, update the signture to DB when not found.
2943 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2944 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2945 }
2946 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2947
2948 dh.lockDevice.RLock()
2949 // Stop the read indication only if it the routine is active
2950 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2951 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2952 // on next execution of the readIndication routine.
2953 if !dh.isReadIndicationRoutineActive {
2954 // Start reading indications
2955 go func() {
2956 if err = dh.readIndications(ctx); err != nil {
2957 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2958 }
2959 }()
2960 }
2961 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302962 } else {
2963 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2964 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2965 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2966 go dh.updateStateRebooted(ctx)
2967 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302968 }
2969 cancel()
2970 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002971 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302972 return
2973 }
2974 }
2975}
2976
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002977func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002978 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002979 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002980 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2981 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2982 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2983 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2984 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002985 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002986 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2987 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002988 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302989
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302990 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002991 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002992 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002993 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002994 DeviceId: dh.device.Id,
2995 OperStatus: voltha.OperStatus_UNKNOWN,
2996 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2997 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002998 _ = 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 -04002999 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303000 /*
3001 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
3002 DeviceId: dh.device.Id,
3003 PortTypeFilter: 0,
3004 OperStatus: voltha.OperStatus_UNKNOWN,
3005 }); err != nil {
3006 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3007 }
3008 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003009
Akash Kankanala041a2122024-10-16 15:49:22 +05303010 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003011 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003012 cloned := proto.Clone(device).(*voltha.Device)
3013 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3014 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3015 dh.device = cloned // update local copy of the device
3016 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003017
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003018 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003019 // Stop the Stats collector
3020 if dh.isCollectorActive {
3021 dh.stopCollector <- true
3022 }
3023 // stop the heartbeat check routine
3024 if dh.isHeartbeatCheckActive {
3025 dh.stopHeartbeatCheck <- true
3026 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003027 // Stop the read indication only if it the routine is active
3028 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3029 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3030 // on next execution of the readIndication routine.
3031 if dh.isReadIndicationRoutineActive {
3032 dh.stopIndications <- true
3033 }
3034 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003035 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303036 }
3037}
kesavand39e0aa32020-01-28 20:58:50 -05003038
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303039func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3040 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3041 if err != nil || device == nil {
3042 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3043 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3044 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3045 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3046 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3047 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3048 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3049 return
3050 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303051 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003052 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303053
3054 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3055 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303056 // First, stop the read indication and heartbeat check routines to prevent any delay
3057 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303058 dh.lockDevice.RLock()
3059 // Stop the read indication only if it the routine is active
3060 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3061 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3062 // on next execution of the readIndication routine.
3063 if dh.isReadIndicationRoutineActive {
3064 dh.stopIndications <- true
3065 }
3066 dh.lockDevice.RUnlock()
3067
bseenivad1c984b2025-01-09 12:54:44 +05303068 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3069 DeviceId: dh.device.Id,
3070 OperStatus: voltha.OperStatus_REBOOTED,
3071 ConnStatus: voltha.ConnectStatus_REACHABLE,
3072 }); err != nil {
3073 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3074 }
3075
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303076 //raise olt communication failure event
3077 raisedTs := time.Now().Unix()
3078 cloned := proto.Clone(device).(*voltha.Device)
3079 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3080 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3081 dh.device = cloned // update local copy of the device
3082 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3083
Gustavo Silva41af9122022-10-11 11:05:13 -03003084 if err := dh.cleanupDeviceResources(ctx); err != nil {
3085 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3086 } else {
3087 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3088 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003089
3090 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303091 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003092 if dh.isCollectorActive {
3093 dh.stopCollector <- true
3094 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303095 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003096 if dh.isHeartbeatCheckActive {
3097 dh.stopHeartbeatCheck <- true
3098 }
3099 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303100
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003101 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303102
Akash Kankanala041a2122024-10-16 15:49:22 +05303103 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303104 dh.adapterPreviouslyConnected = false
3105 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303106 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3107 if err != nil || childDevices == nil {
3108 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3109 continue
3110 }
3111 if len(childDevices.Items) == 0 {
3112 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3113 break
3114 } else {
3115 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3116 time.Sleep(5 * time.Second)
3117 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303118 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303119 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003120 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303121 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3122 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303123}
3124
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303125// EnableOnuSerialNumber to enable onu serial number
3126func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3127 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3128 onuSerialNumber := device.SerialNumber
3129
3130 // fetch interfaceid from PortNo
3131 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3132
3133 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3134 if err != nil {
3135 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3136 log.Fields{
3137 "devicer-id": dh.device.Id,
3138 "serial-number": onuSerialNumber}, err).Log()
3139 }
3140
3141 onuIntf := &oop.InterfaceOnuSerialNumber{
3142 IntfId: ponID,
3143 OnuSerialNumber: sn,
3144 }
3145 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3146
3147 if err != nil {
3148 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3149 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3150 "device-id": dh.device.Id,
3151 "onu-serial-number": onuSerialNumber}, err)
3152 }
3153 return nil
3154}
3155
3156// DisableOnuSerialNumber to disable onu serial number
3157func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3158 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3159 onuSerialNumber := device.SerialNumber
3160 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3161 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3162 if err != nil {
3163 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3164 log.Fields{
3165 "devicer-id": dh.device.Id,
3166 "serial-number": onuSerialNumber}, err).Log()
3167 }
3168
3169 onuIntf := &oop.InterfaceOnuSerialNumber{
3170 OnuSerialNumber: sn,
3171 IntfId: ponID,
3172 }
3173 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3174
3175 if err != nil {
3176 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3177 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3178 "device-id": dh.device.Id,
3179 "onu-serial-number": onuSerialNumber}, err)
3180 }
3181 return nil
3182}
3183
3184// EnableOnu to enable onu
3185func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3186 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3187 onuSerialNumber := device.SerialNumber
3188 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3189 if InCacheOnuDev == nil {
3190 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3191 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3192 "device-id": dh.device.Id,
3193 "onu-serial-number": onuSerialNumber}, nil)
3194 }
3195 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})
3196
3197 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3198 if err != nil {
3199 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3200 log.Fields{
3201 "device-id": dh.device.Id,
3202 "serial-number": onuSerialNumber}, err).Log()
3203 }
3204
3205 onuIntf := &oop.InterfaceOnuSerialNumber{
3206 OnuSerialNumber: sn,
3207 IntfId: InCacheOnuDev.intfID,
3208 }
3209 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3210 OnuId: InCacheOnuDev.onuID,
3211 IntfIdSerialNum: onuIntf,
3212 }
3213 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3214
3215 if err != nil {
3216 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3217 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3218 "olt-device-id": dh.device.Id,
3219 "onu-serial-number": onuSerialNumber}, err)
3220 }
3221 return nil
3222}
3223
3224// DisableOnu to disable onu
3225func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3226 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3227 onuSerialNumber := device.SerialNumber
3228 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3229 if InCacheOnuDev == nil {
3230 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3231 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3232 "device-id": dh.device.Id,
3233 "onu-serial-number": onuSerialNumber}, nil)
3234 }
3235 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})
3236
3237 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3238 if err != nil {
3239 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3240 log.Fields{
3241 "device-id": dh.device.Id,
3242 "serial-number": onuSerialNumber}, err).Log()
3243 }
3244
3245 onuIntf := &oop.InterfaceOnuSerialNumber{
3246 OnuSerialNumber: sn,
3247 IntfId: InCacheOnuDev.intfID,
3248 }
3249 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3250 OnuId: InCacheOnuDev.onuID,
3251 IntfIdSerialNum: onuIntf,
3252 }
3253 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3254
3255 if err != nil {
3256 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3257 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3258 "olt-device-id": dh.device.Id,
3259 "onu-serial-number": onuSerialNumber}, err)
3260 }
3261 return nil
3262}
3263
kesavand39e0aa32020-01-28 20:58:50 -05003264// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003265func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3266 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3267 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003268}
3269
3270// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003271func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3272 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3273 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003274}
3275
Mahir Gunyela2e68702022-12-07 00:00:42 -08003276// 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 +00003277func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3278 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003279 if port.GetType() == voltha.Port_ETHERNET_NNI {
3280 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003281 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303282 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303283 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003284 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003285 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003286 }
3287 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003288 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003289 ponIntf := &oop.Interface{IntfId: ponID}
3290 var operStatus voltha.OperStatus_Types
3291 if enablePort {
3292 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303293 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003294
3295 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303296 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003297 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003298 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003299 }
3300 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003301 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003302 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003303 } else {
3304 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303305 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003306 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303307 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003308 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003309 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003310 }
3311 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003312 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003313 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003314 }
khenaidoodc2116e2021-10-19 17:33:19 -04003315 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003316 DeviceId: dh.device.Id,
3317 PortType: voltha.Port_PON_OLT,
3318 PortNo: port.PortNo,
3319 OperStatus: operStatus,
3320 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303321 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303322 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003323 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003324 }
3325 return nil
3326}
3327
Mahir Gunyela2e68702022-12-07 00:00:42 -08003328// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003329func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003330 // Disable the port and update the oper_port_status to core
3331 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003332 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003333 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003334 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303335 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303336 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003337 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003338 }
3339 }
3340 }
3341 return nil
3342}
3343
Mahir Gunyela2e68702022-12-07 00:00:42 -08003344// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003345func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3346 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3347 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003348 if port.Type == voltha.Port_ETHERNET_NNI {
3349 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003350 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003351 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003352 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003353 }
3354 }
3355 if port.Type == voltha.Port_PON_OLT {
3356 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003357 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003358 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003359 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003360 }
3361 }
3362 }
3363}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003364
3365// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003366func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003367 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003368 if dh.getDeviceDeletionInProgressFlag() {
3369 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3370 // will reboot, so everything will be reset on the pOLT too.
3371 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3372 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3373 return nil
3374 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303375
3376 if dh.transitionMap.currentDeviceState != deviceStateUp {
3377 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})
3378 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3379 }
3380
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003381 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003382 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003383
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003384 var sn *oop.SerialNumber
3385 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003386 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303387 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003388 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303389 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003390 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003391 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003392
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003393 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303394 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003395 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003396 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3397 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3398 "device-id": dh.device.Id,
3399 "intf-id": intfID,
3400 "onuID": onuID,
3401 "err": err})
3402 } else {
3403 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003404 // Delete flows from device before schedulers and queue
3405 // Clear flowids for gem cache.
3406 removedFlows := []uint64{}
3407 for _, gem := range onuGem.GemPorts {
3408 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3409 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303410 // multiple gem port can have the same flow id
3411 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003412 var alreadyRemoved bool
3413 for _, removedFlowID := range removedFlows {
3414 if removedFlowID == flowID {
3415 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3416 alreadyRemoved = true
3417 break
3418 }
3419 }
3420 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003421 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003422 removedFlows = appendUnique64bit(removedFlows, flowID)
3423 }
3424 }
3425 }
3426 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3427 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003428 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3429 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3430 "device-id": dh.device.Id,
3431 "onu-device": onu,
3432 "err": err})
3433 }
yasin saplibddc2d72022-02-08 13:10:17 +00003434 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003435 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3436 "intf-id": intfID,
3437 "onu-device": onu,
3438 "onu-gem": onuGem,
3439 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303440 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003441 }
3442 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003443 }
yasin saplibddc2d72022-02-08 13:10:17 +00003444 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003445 dh.onus.Delete(onuKey)
3446 dh.discOnus.Delete(onuSn)
3447
3448 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003449 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303450 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303451 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003452 "onu-id": onuID}, err).Log()
3453 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003454
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003455 return nil
3456}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003457func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3458 flow := &oop.Flow{FlowId: flowID}
3459 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3460 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3461 "device-id": dh.device.Id})
3462 } else {
3463 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3464 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3465 "device-id": dh.device.Id,
3466 "err": err})
3467 }
3468 }
3469}
Girish Gowdracefae192020-03-19 18:14:10 -07003470
3471func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003472 for _, field := range flow_utils.GetOfbFields(flow) {
3473 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003474 return field.GetPort()
3475 }
3476 }
3477 return InvalidPort
3478}
3479
3480func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003481 for _, action := range flow_utils.GetActions(flow) {
3482 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003483 if out := action.GetOutput(); out != nil {
3484 return out.GetPort()
3485 }
3486 }
3487 }
3488 return InvalidPort
3489}
3490
Girish Gowdracefae192020-03-19 18:14:10 -07003491func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3492 inPort := getInPortFromFlow(flow)
3493 outPort := getOutPortFromFlow(flow)
3494
3495 if inPort == InvalidPort || outPort == InvalidPort {
3496 return inPort, outPort
3497 }
3498
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003499 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003500 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003501 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003502 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003503 return uniPort, outPort
3504 }
3505 }
3506 } else {
3507 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003508 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003509 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003510 return inPort, uniPort
3511 }
3512 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003513 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003514 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003515 return uniPort, outPort
3516 }
3517 }
3518 }
3519
3520 return InvalidPort, InvalidPort
3521}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003522
3523func extractOmciTransactionID(omciPkt []byte) uint16 {
3524 if len(omciPkt) > 3 {
3525 d := omciPkt[0:2]
3526 transid := binary.BigEndian.Uint16(d)
3527 return transid
3528 }
3529 return 0
3530}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003531
3532// StoreOnuDevice stores the onu parameters to the local cache.
3533func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3534 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3535 dh.onus.Store(onuKey, onuDevice)
3536}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003537
khenaidoodc2116e2021-10-19 17:33:19 -04003538func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003539 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003540 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003541 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003542 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003543 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003544 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003545 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003546 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3547 return nil, err
3548 }
3549 ID = device.ProxyAddress.GetOnuId()
3550 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3551 valueparam.Onu = &Onu
3552 valueparam.Value = value
3553
3554 // This API is unsupported until agent patch is added
3555 resp.Unsupported = uint32(value)
3556 _ = ctx
3557
3558 // Uncomment this code once agent changes are complete and tests
3559 /*
3560 resp, err = dh.Client.GetValue(ctx, valueparam)
3561 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003562 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003563 return nil, err
3564 }
3565 */
3566
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003567 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 -08003568 return resp, nil
3569}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003570
Akash Kankanala041a2122024-10-16 15:49:22 +05303571func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003572 // Default to NNI
3573 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003574 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003575 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003576 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003577 }
3578 return intfID
3579}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003580
Akash Kankanala041a2122024-10-16 15:49:22 +05303581func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003582 dh.perPonOnuIndicationChannelLock.Lock()
3583 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3584 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003585 return ch.indicationChannel
3586 }
3587 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303588 // We create a buffered channel here to avoid calling function to be blocked
3589 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003590 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003591 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003592 stopChannel: make(chan struct{}),
3593 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003594 dh.perPonOnuIndicationChannel[intfID] = channels
3595 dh.perPonOnuIndicationChannelLock.Unlock()
3596 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003597 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003598}
3599
Mahir Gunyelb0046752021-02-26 13:51:05 -08003600func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3601 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3602 dh.perPonOnuIndicationChannelLock.Lock()
3603 defer dh.perPonOnuIndicationChannelLock.Unlock()
3604 for _, v := range dh.perPonOnuIndicationChannel {
3605 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003606 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003607 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003608}
3609
Mahir Gunyelb0046752021-02-26 13:51:05 -08003610func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3611 ind := onuIndicationMsg{
3612 ctx: ctx,
3613 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003614 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003615 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003616 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303617 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003618}
3619
Mahir Gunyelb0046752021-02-26 13:51:05 -08003620func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003621 for {
3622 select {
3623 // process one indication per onu, before proceeding to the next one
3624 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003625 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003626 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003627 "ind": indication})
3628 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003629 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003630 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003631 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3632 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003633 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003634 }
3635 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003636 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003637 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3638 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003639 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003640 }
3641 }
3642 case <-onuChannels.stopChannel:
3643 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3644 close(onuChannels.indicationChannel)
3645 return
3646 }
3647 }
3648}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003649
3650// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3651// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003652func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003653 if dh.getDeviceDeletionInProgressFlag() {
3654 // The device itself is going to be reset as part of deletion. So nothing to be done.
3655 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3656 return nil
3657 }
3658
Girish Gowdra491a9c62021-01-06 16:43:07 -08003659 // Step1 : Fill McastFlowOrGroupControlBlock
3660 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3661 // Step3 : Wait on response channel for response
3662 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003663 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003664 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3665 errChan := make(chan error)
3666 var groupID uint32
3667 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3668 ctx: ctx,
3669 flowOrGroupAction: action,
3670 flow: flow,
3671 group: group,
3672 errChan: &errChan,
3673 }
3674 if flow != nil {
3675 groupID = flow_utils.GetGroup(flow)
3676 } else if group != nil {
3677 groupID = group.Desc.GroupId
3678 } else {
3679 return errors.New("flow-and-group-both-nil")
3680 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003681 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3682 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3683 // Derive the appropriate go routine to handle the request by a simple module operation.
3684 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3685 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3686 // Wait for handler to return error value
3687 err := <-errChan
3688 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3689 return err
3690 }
3691 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3692 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003693}
3694
3695// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003696func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003697 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003698 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003699 // block on the channel to receive an incoming mcast flow/group
3700 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003701 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3702 if mcastFlowOrGroupCb.flow != nil {
3703 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3704 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3705 log.Fields{"device-id": dh.device.Id,
3706 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003707 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3708 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3709 for _, flMgr := range dh.flowMgr {
3710 if flMgr != nil {
3711 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3712 break
3713 }
3714 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003715 // Pass the return value over the return channel
3716 *mcastFlowOrGroupCb.errChan <- err
3717 } else { // flow remove
3718 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3719 log.Fields{"device-id": dh.device.Id,
3720 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003721 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3722 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3723 for _, flMgr := range dh.flowMgr {
3724 if flMgr != nil {
3725 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3726 break
3727 }
3728 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003729 // Pass the return value over the return channel
3730 *mcastFlowOrGroupCb.errChan <- err
3731 }
3732 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303733 switch mcastFlowOrGroupCb.flowOrGroupAction {
3734 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003735 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3736 log.Fields{"device-id": dh.device.Id,
3737 "groupToAdd": mcastFlowOrGroupCb.group})
3738 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3739 // Pass the return value over the return channel
3740 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303741 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003742 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3743 log.Fields{"device-id": dh.device.Id,
3744 "groupToModify": mcastFlowOrGroupCb.group})
3745 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3746 // Pass the return value over the return channel
3747 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303748 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003749 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3750 log.Fields{"device-id": dh.device.Id,
3751 "groupToRemove": mcastFlowOrGroupCb.group})
3752 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3753 // Pass the return value over the return channel
3754 *mcastFlowOrGroupCb.errChan <- err
3755 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003756 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003757 case <-stopHandler:
3758 dh.mcastHandlerRoutineActive[routineIndex] = false
3759 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003760 }
3761 }
3762}
kesavand62126212021-01-12 04:56:06 -05003763
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003764// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003765func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003766 for i, v := range dh.stopMcastHandlerRoutine {
3767 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003768 select {
3769 case v <- true:
3770 case <-time.After(time.Second * 5):
3771 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3772 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003773 }
3774 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003775
3776 if dh.incomingMcastFlowOrGroup != nil {
3777 for k := range dh.incomingMcastFlowOrGroup {
3778 if dh.incomingMcastFlowOrGroup[k] != nil {
3779 dh.incomingMcastFlowOrGroup[k] = nil
3780 }
3781 }
3782 dh.incomingMcastFlowOrGroup = nil
3783 }
3784
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003785 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003786 logger.Debug(ctx, "stopped all mcast handler routines")
3787}
3788
Akash Kankanala041a2122024-10-16 15:49:22 +05303789// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003790func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003791 singleValResp := extension.SingleGetValueResponse{
3792 Response: &extension.GetValueResponse{
3793 Response: &extension.GetValueResponse_PortCoutners{
3794 PortCoutners: &extension.GetOltPortCountersResponse{},
3795 },
3796 },
3797 }
3798
Akash Kankanala041a2122024-10-16 15:49:22 +05303799 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003800 return &extension.SingleGetValueResponse{
3801 Response: &extension.GetValueResponse{
3802 Status: status,
3803 ErrReason: reason,
3804 },
3805 }
3806 }
3807
3808 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3809 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303810 // send error response
kesavand62126212021-01-12 04:56:06 -05003811 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3812 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3813 }
3814 statIndChn := make(chan bool, 1)
3815 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3816 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303817 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003818
3819 go func() {
3820 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3821 if err != nil {
3822 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3823 }
3824 }()
3825 select {
3826 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303827 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003828 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3829 case <-time.After(oltPortInfoTimeout * time.Second):
3830 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3831 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3832 case <-ctx.Done():
3833 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3834 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3835 }
mgouda86543582025-10-29 20:58:16 +05303836 switch oltPortInfo.PortType {
3837 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303838 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003839 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003840 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3841 cmnni := dh.portStats.collectNNIMetrics(intfID)
3842 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303843 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003844 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3845 }
3846 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3847 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303848 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003849 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003850 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003851 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3852 cmpon := dh.portStats.collectPONMetrics(intfID)
3853 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303854 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003855 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3856 }
3857 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3858 return &singleValResp
3859 }
3860 }
3861 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3862}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303863
Akash Kankanala041a2122024-10-16 15:49:22 +05303864//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303865func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303866 singleValResp := extension.SingleGetValueResponse{
3867 Response: &extension.GetValueResponse{
3868 Status: extension.GetValueResponse_OK,
3869 Response: &extension.GetValueResponse_OffloadedAppsStats{
3870 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3871 },
3872 },
3873 }
3874
3875 return &singleValResp
3876}
3877
Akash Kankanala041a2122024-10-16 15:49:22 +05303878//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303879func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303880 singleValResp := extension.SingleSetValueResponse{
3881 Response: &extension.SetValueResponse{
3882 Status: extension.SetValueResponse_OK,
3883 },
3884 }
3885
3886 return &singleValResp
3887}
3888
Akash Kankanala041a2122024-10-16 15:49:22 +05303889//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303890func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303891 singleValResp := extension.SingleSetValueResponse{
3892 Response: &extension.SetValueResponse{
3893 Status: extension.SetValueResponse_OK,
3894 },
3895 }
3896
3897 return &singleValResp
3898}
3899
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303900func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303901 singleValResp := extension.SingleGetValueResponse{
3902 Response: &extension.GetValueResponse{
3903 Response: &extension.GetValueResponse_OnuPonCounters{
3904 OnuPonCounters: &extension.GetOnuCountersResponse{},
3905 },
3906 },
3907 }
3908
Akash Kankanala041a2122024-10-16 15:49:22 +05303909 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303910 return &extension.SingleGetValueResponse{
3911 Response: &extension.GetValueResponse{
3912 Status: status,
3913 ErrReason: reason,
3914 },
3915 }
3916 }
3917 intfID := onuPonInfo.IntfId
3918 onuID := onuPonInfo.OnuId
3919 onuKey := dh.formOnuKey(intfID, onuID)
3920
3921 if _, ok := dh.onus.Load(onuKey); !ok {
3922 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3923 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3924 }
3925 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3926 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3927 if cmnni == nil {
3928 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3929 }
3930 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3931 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303932}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003933
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303934func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3935 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3936 if err != nil {
3937 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3938 return nil, err
3939 }
3940 if onuGemInfo != nil {
3941 if len(onuGemInfo.UniPorts) == 0 {
3942 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3943 return nil, err
3944 }
3945 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3946 return onuGemInfo, nil
3947 }
3948 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3949 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3950}
3951
3952func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3953 var err error
3954 var allocStats *oop.OnuAllocIdStatistics
3955 var onuGemStats *oop.GemPortStatistics
3956 for _, uni := range onuGemInfo.UniPorts {
3957 uniID := plt.UniIDFromPortNum(uni)
3958 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3959 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3960 if len(tpIDs) == 0 {
3961 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3962 continue
3963 }
3964 for _, tpId := range tpIDs {
3965 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3966 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3967 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3968 if techProfileInstance != nil {
3969 switch tpInst := techProfileInstance.(type) {
3970 case *tp_pb.TechProfileInstance:
3971 allocId := tpInst.UsScheduler.AllocId
3972 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3973 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3974 if err != nil {
3975 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3976 return err
3977 }
3978 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3979 allocIdInfo.AllocId = allocStats.AllocId
3980 allocIdInfo.RxBytes = allocStats.RxBytes
3981
3982 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3983
3984 gemPorts := tpInst.UpstreamGemPortAttributeList
3985 for _, gem := range gemPorts {
3986 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3987 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
3988 if err != nil {
3989 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
3990 return err
3991 }
3992 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
3993 gemStatsInfo.GemId = onuGemStats.GemportId
3994 gemStatsInfo.RxBytes = onuGemStats.RxBytes
3995 gemStatsInfo.RxPackets = onuGemStats.RxPackets
3996 gemStatsInfo.TxBytes = onuGemStats.TxBytes
3997 gemStatsInfo.TxPackets = onuGemStats.TxPackets
3998
3999 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
4000 }
4001 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
4002
4003 default:
4004 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4005 return err
4006 }
4007 } else {
4008 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4009 continue
4010 }
4011 }
4012 }
4013 return err
4014}
4015
4016//nolint:unparam
4017func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4018 singleValResp := extension.SingleGetValueResponse{
4019 Response: &extension.GetValueResponse{
4020 Status: extension.GetValueResponse_OK,
4021 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4022 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4023 },
4024 },
4025 }
4026 errResp := func(status extension.GetValueResponse_Status,
4027 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4028 return &extension.SingleGetValueResponse{
4029 Response: &extension.GetValueResponse{
4030 Status: status,
4031 ErrReason: reason,
4032 },
4033 }
4034 }
4035
4036 var intfID, onuID uint32
4037 if onuDevice != nil {
4038 onuID = onuDevice.ProxyAddress.OnuId
4039 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4040 }
4041
4042 onuKey := dh.formOnuKey(intfID, onuID)
4043 if _, ok := dh.onus.Load(onuKey); !ok {
4044 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4045 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4046 }
4047 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4048
4049 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4050 if err == nil {
4051 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4052 if err != nil {
4053 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4054 }
4055 } else {
4056 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4057 }
4058 return &singleValResp
4059}
4060
nikesh.krishnanc8473432023-06-14 12:14:54 +05304061func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304062 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
4063 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
4064 if err != nil {
4065 return nil, err
4066 }
4067 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304068}
4069
4070func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304071 Intf := oop.Interface{IntfId: intfID}
4072 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
4073 if err != nil {
4074 return nil, err
4075 }
4076 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304077}
4078
Gamze Abaka85e9a142021-05-26 13:41:39 +00004079func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004080 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
4081 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4082 if err != nil {
4083 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4084 return generateSingleGetValueErrorResponse(err)
4085 }
4086 return &extension.SingleGetValueResponse{
4087 Response: &extension.GetValueResponse{
4088 Status: extension.GetValueResponse_OK,
4089 Response: &extension.GetValueResponse_RxPower{
4090 RxPower: &extension.GetRxPowerResponse{
4091 IntfId: rxPowerRequest.IntfId,
4092 OnuId: rxPowerRequest.OnuId,
4093 Status: rxPower.Status,
4094 FailReason: rxPower.FailReason.String(),
4095 RxPower: rxPower.RxPowerMeanDbm,
4096 },
4097 },
4098 },
4099 }
4100}
4101
praneeth nalmas55616d62023-02-06 09:19:18 +05304102func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304103 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304104 return &extension.SingleGetValueResponse{
4105 Response: &extension.GetValueResponse{
4106 Status: status,
4107 ErrReason: reason,
4108 },
4109 }
4110 }
4111
4112 resp := extension.SingleGetValueResponse{
4113 Response: &extension.GetValueResponse{
4114 Status: extension.GetValueResponse_OK,
4115 Response: &extension.GetValueResponse_OltRxPower{
4116 OltRxPower: &extension.GetOltRxPowerResponse{},
4117 },
4118 },
4119 }
4120
4121 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4122 portLabel := OltRxPowerRequest.PortLabel
4123 serialNumber := OltRxPowerRequest.OnuSn
4124
4125 portInfo := strings.Split(portLabel, "-")
4126 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4127
4128 if err != nil {
4129 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4130 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4131 }
4132
4133 if portInfo[0] != "pon" {
4134 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4135 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4136 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304137
4138 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304139 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4140 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304141 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
4142 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4143 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304144 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4145 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304146 }
4147
4148 rxPowerValue := extension.RxPower{}
4149 rxPowerValue.OnuSn = onuDev.serialNumber
4150 rxPowerValue.Status = rxPower.GetStatus()
4151 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4152 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4153
4154 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304155 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304156 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4157 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4158 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304159 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304160 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304161 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304162 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05304163 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4164 if err != nil {
4165 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4166 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304167 rxPowerValue := extension.RxPower{}
4168 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4169 rxPowerValue.Status = rxPower.GetStatus()
4170 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4171 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4172
4173 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4174 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304175 }
4176 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4177 return true
4178 })
4179 }
4180 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4181 return &resp
4182}
4183
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304184func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4185 errResp := func(status extension.GetValueResponse_Status,
4186 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4187 return &extension.SingleGetValueResponse{
4188 Response: &extension.GetValueResponse{
4189 Status: status,
4190 ErrReason: reason,
4191 },
4192 }
4193 }
4194
4195 resp := extension.SingleGetValueResponse{
4196 Response: &extension.GetValueResponse{
4197 Status: extension.GetValueResponse_OK,
4198 Response: &extension.GetValueResponse_OltPonStatsResponse{
4199 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4200 },
4201 },
4202 }
4203
4204 portLabel := ponStatsRequest.GetPortLabel()
4205 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4206
4207 portInfo := strings.Split(portLabel, "-")
4208 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4209
4210 if err != nil {
4211 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4212 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4213 }
4214
4215 if portInfo[0] != "pon" {
4216 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4217 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4218 }
4219
4220 Interface := oop.Interface{IntfId: uint32(portNumber)}
4221 ponStats, err := dh.Client.GetPonPortStatistics(ctx, &Interface)
4222 if err != nil {
4223 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4224 return generateSingleGetValueErrorResponse(err)
4225 }
4226
4227 ponPortStats := resp.Response.GetOltPonStatsResponse()
4228 ponPortStats.PonPort = uint32(portNumber)
4229 ponPortStats.PortStatistics = ponStats
4230
4231 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4232 return &resp
4233}
4234
4235func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4236 errResp := func(status extension.GetValueResponse_Status,
4237 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4238 return &extension.SingleGetValueResponse{
4239 Response: &extension.GetValueResponse{
4240 Status: status,
4241 ErrReason: reason,
4242 },
4243 }
4244 }
4245
4246 resp := extension.SingleGetValueResponse{
4247 Response: &extension.GetValueResponse{
4248 Status: extension.GetValueResponse_OK,
4249 Response: &extension.GetValueResponse_OltNniStatsResponse{
4250 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4251 },
4252 },
4253 }
4254
4255 portLabel := nniStatsRequest.GetPortLabel()
4256 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4257
4258 portInfo := strings.Split(portLabel, "-")
4259 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4260
4261 if err != nil {
4262 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4263 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4264 }
4265
4266 if portInfo[0] != "nni" {
4267 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4268 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4269 }
4270
4271 Interface := oop.Interface{IntfId: uint32(portNumber)}
4272 nniStats, err := dh.Client.GetNniPortStatistics(ctx, &Interface)
4273 if err != nil {
4274 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4275 return generateSingleGetValueErrorResponse(err)
4276 }
4277
4278 nniPortStats := resp.Response.GetOltNniStatsResponse()
4279 nniPortStats.NniPort = uint32(portNumber)
4280 nniPortStats.PortStatistics = nniStats
4281
4282 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4283 return &resp
4284}
4285
Akash Kankanala041a2122024-10-16 15:49:22 +05304286// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004287func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304288 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004289 return &extension.SingleGetValueResponse{
4290 Response: &extension.GetValueResponse{
4291 Status: status,
4292 ErrReason: reason,
4293 },
4294 }
4295 }
4296
4297 if err != nil {
4298 if e, ok := status.FromError(err); ok {
4299 switch e.Code() {
4300 case codes.Internal:
4301 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4302 case codes.DeadlineExceeded:
4303 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4304 case codes.Unimplemented:
4305 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4306 case codes.NotFound:
4307 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4308 }
4309 }
4310 }
4311
4312 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4313}
khenaidoo106c61a2021-08-11 18:05:46 -04004314
4315/*
4316Helper functions to communicate with Core
4317*/
4318
4319func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4320 cClient, err := dh.coreClient.GetCoreServiceClient()
4321 if err != nil || cClient == nil {
4322 return nil, err
4323 }
4324 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4325 defer cancel()
4326 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4327}
4328
khenaidoodc2116e2021-10-19 17:33:19 -04004329func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004330 cClient, err := dh.coreClient.GetCoreServiceClient()
4331 if err != nil || cClient == nil {
4332 return nil, err
4333 }
4334 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4335 defer cancel()
4336 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4337}
4338
khenaidoodc2116e2021-10-19 17:33:19 -04004339func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004340 cClient, err := dh.coreClient.GetCoreServiceClient()
4341 if err != nil || cClient == nil {
4342 return err
4343 }
4344 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4345 defer cancel()
4346 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4347 return err
4348}
4349
4350func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4351 cClient, err := dh.coreClient.GetCoreServiceClient()
4352 if err != nil || cClient == nil {
4353 return nil, err
4354 }
4355 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4356 defer cancel()
4357 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4358}
4359
4360func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4361 cClient, err := dh.coreClient.GetCoreServiceClient()
4362 if err != nil || cClient == nil {
4363 return nil, err
4364 }
4365 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4366 defer cancel()
4367 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4368}
4369
4370func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4371 cClient, err := dh.coreClient.GetCoreServiceClient()
4372 if err != nil || cClient == nil {
4373 return err
4374 }
4375 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4376 defer cancel()
4377 _, err = cClient.DeviceUpdate(subCtx, device)
4378 return err
4379}
4380
khenaidoodc2116e2021-10-19 17:33:19 -04004381func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004382 cClient, err := dh.coreClient.GetCoreServiceClient()
4383 if err != nil || cClient == nil {
4384 return nil, err
4385 }
4386 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4387 defer cancel()
4388 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4389}
4390
khenaidoodc2116e2021-10-19 17:33:19 -04004391func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004392 cClient, err := dh.coreClient.GetCoreServiceClient()
4393 if err != nil || cClient == nil {
4394 return err
4395 }
4396 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4397 defer cancel()
4398 _, err = cClient.SendPacketIn(subCtx, pkt)
4399 return err
4400}
4401
4402func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4403 cClient, err := dh.coreClient.GetCoreServiceClient()
4404 if err != nil || cClient == nil {
4405 return err
4406 }
4407 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4408 defer cancel()
4409 _, err = cClient.PortCreated(subCtx, port)
4410 return err
4411}
4412
khenaidoodc2116e2021-10-19 17:33:19 -04004413func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004414 cClient, err := dh.coreClient.GetCoreServiceClient()
4415 if err != nil || cClient == nil {
4416 return err
4417 }
4418 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4419 defer cancel()
4420 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4421 return err
4422}
4423
khenaidoodc2116e2021-10-19 17:33:19 -04004424func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004425 cClient, err := dh.coreClient.GetCoreServiceClient()
4426 if err != nil || cClient == nil {
4427 return err
4428 }
4429 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4430 defer cancel()
4431 _, err = cClient.PortStateUpdate(subCtx, portState)
4432 return err
4433}
4434
khenaidoodc2116e2021-10-19 17:33:19 -04004435func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004436 cClient, err := dh.coreClient.GetCoreServiceClient()
4437 if err != nil || cClient == nil {
4438 return nil, err
4439 }
4440 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4441 defer cancel()
4442 return cClient.GetDevicePort(subCtx, portFilter)
4443}
4444
nikesh.krishnanc8473432023-06-14 12:14:54 +05304445func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4446 cClient, err := dh.coreClient.GetCoreServiceClient()
4447 if err != nil || cClient == nil {
4448 return nil, err
4449 }
4450 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4451 defer cancel()
4452 return cClient.GetPorts(subCtx, portFilter)
4453}
4454
khenaidoo106c61a2021-08-11 18:05:46 -04004455/*
4456Helper functions to communicate with child adapter
4457*/
4458
khenaidoodc2116e2021-10-19 17:33:19 -04004459func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004460 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4461 if err != nil || aClient == nil {
4462 return err
4463 }
4464 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4465 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4466 defer cancel()
4467 _, err = aClient.OmciIndication(subCtx, response)
4468 return err
4469}
4470
khenaidoodc2116e2021-10-19 17:33:19 -04004471func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004472 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4473 if err != nil || aClient == nil {
4474 return err
4475 }
4476 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4477 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4478 defer cancel()
4479 _, err = aClient.OnuIndication(subCtx, onuInd)
4480 return err
4481}
4482
khenaidoodc2116e2021-10-19 17:33:19 -04004483func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004484 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4485 if err != nil || aClient == nil {
4486 return err
4487 }
4488 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4489 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4490 defer cancel()
4491 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4492 return err
4493}
4494
khenaidoodc2116e2021-10-19 17:33:19 -04004495func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004496 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4497 if err != nil || aClient == nil {
4498 return err
4499 }
4500 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4501 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4502 defer cancel()
4503 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4504 return err
4505}
4506
khenaidoodc2116e2021-10-19 17:33:19 -04004507func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004508 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4509 if err != nil || aClient == nil {
4510 return err
4511 }
4512 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4513 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4514 defer cancel()
4515 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4516 return err
4517}
4518
4519/*
4520Helper functions for remote communication
4521*/
4522
4523// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4524// supports is deleted
4525func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4526 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4527
4528 dh.lockChildAdapterClients.Lock()
4529 defer dh.lockChildAdapterClients.Unlock()
4530 if _, ok := dh.childAdapterClients[endpoint]; ok {
4531 // Already set
4532 return nil
4533 }
4534
4535 // Setup child's adapter grpc connection
4536 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004537 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4538 dh.cfg.AdapterEndpoint,
4539 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004540 "onu_inter_adapter_service.OnuInterAdapterService",
4541 dh.onuInterAdapterRestarted,
4542 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004543 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4544 return err
4545 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304546 retryCodes := []codes.Code{
4547 codes.Unavailable, // server is currently unavailable
4548 codes.DeadlineExceeded, // deadline for the operation was exceeded
4549 }
4550 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4551 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 -04004552
nikesh.krishnand9812542023-08-01 18:31:39 +05304553 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004554 // Wait until we have a connection to the child adapter.
4555 // Unlimited retries or until context expires
4556 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4557 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4558 for {
4559 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4560 if err == nil && client != nil {
4561 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4562 break
4563 }
4564 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4565 // Backoff
4566 if err = backoff.Backoff(subCtx); err != nil {
4567 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4568 break
4569 }
4570 }
4571 return nil
4572}
4573
khenaidoodc2116e2021-10-19 17:33:19 -04004574func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004575 // First check from cache
4576 dh.lockChildAdapterClients.RLock()
4577 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4578 dh.lockChildAdapterClients.RUnlock()
4579 return cgClient.GetOnuInterAdapterServiceClient()
4580 }
4581 dh.lockChildAdapterClients.RUnlock()
4582
4583 // Set the child connection - can occur on restarts
4584 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4585 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4586 cancel()
4587 if err != nil {
4588 return nil, err
4589 }
4590
4591 // Get the child client now
4592 dh.lockChildAdapterClients.RLock()
4593 defer dh.lockChildAdapterClients.RUnlock()
4594 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4595 return cgClient.GetOnuInterAdapterServiceClient()
4596 }
4597 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4598}
4599
4600func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4601 dh.lockChildAdapterClients.Lock()
4602 defer dh.lockChildAdapterClients.Unlock()
4603 for key, client := range dh.childAdapterClients {
4604 client.Stop(ctx)
4605 delete(dh.childAdapterClients, key)
4606 }
4607}
4608
khenaidooefff76e2021-12-15 16:51:30 -05004609// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4610func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4611 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004612 return nil
4613}
4614
khenaidooefff76e2021-12-15 16:51:30 -05004615// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4616func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4617 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004618 return nil
4619 }
khenaidooefff76e2021-12-15 16:51:30 -05004620 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004621}
Girish Gowdra950326e2021-11-05 12:43:24 -07004622
4623func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4624 dh.lockDevice.Lock()
4625 defer dh.lockDevice.Unlock()
4626 dh.isDeviceDeletionInProgress = flag
4627}
4628
4629func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4630 dh.lockDevice.RLock()
4631 defer dh.lockDevice.RUnlock()
4632 return dh.isDeviceDeletionInProgress
4633}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004634
4635// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4636// Returns false if waiting timed out.
4637func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4638 c := make(chan struct{})
4639 go func() {
4640 defer close(c)
4641 wg.Wait()
4642 }()
4643 select {
4644 case <-c:
4645 return true // completed normally
4646 case <-time.After(timeout):
4647 return false // timed out
4648 }
4649}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304650
4651func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4652 val, err := json.Marshal(signature)
4653 if err != nil {
4654 logger.Error(ctx, "failed-to-marshal")
4655 return
4656 }
4657 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4658 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4659 }
4660}
4661
4662func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4663 var signature uint32
4664
4665 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4666 if er == nil {
4667 if Value != nil {
4668 Val, er := kvstore.ToByte(Value.Value)
4669 if er != nil {
4670 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4671 return signature
4672 }
4673 if er = json.Unmarshal(Val, &signature); er != nil {
4674 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4675 return signature
4676 }
4677 }
4678 }
4679 return signature
4680}