blob: 30bcbf9e0d5b9d086df86692c8cffe1f4028723a [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Phaneendra Manda4c62c802019-03-06 21:37:49 +05303
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Mahir Gunyela2e68702022-12-07 00:00:42 -080017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
Abhay Kumard3f18512025-12-09 07:51:12 +000042 grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
khenaidoo106c61a2021-08-11 18:05:46 -040043 "github.com/opencord/voltha-lib-go/v7/pkg/config"
44 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
45 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
46 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070047 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040048 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080049
nikesh.krishnand9812542023-08-01 18:31:39 +053050 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
khenaidoo106c61a2021-08-11 18:05:46 -040051 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053052 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080053 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040056 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040057 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
58 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040059 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
60 oop "github.com/opencord/voltha-protos/v5/go/openolt"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +053061 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
khenaidoo106c61a2021-08-11 18:05:46 -040062 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070063 "google.golang.org/grpc"
nikesh.krishnand9812542023-08-01 18:31:39 +053064 codes "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040065 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053066)
67
salmansiddiqui7ac62132019-08-22 03:58:50 +000068// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040069const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080070 InvalidPort = 0xffffffff
71 MaxNumOfGroupHandlerChannels = 256
72
73 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
74 McastFlowOrGroupModify = "McastFlowOrGroupModify"
75 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050076 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010077
78 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053079 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040080)
81
Mahir Gunyela2e68702022-12-07 00:00:42 -080082// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053083type DeviceHandler struct {
Akash Kankanala041a2122024-10-16 15:49:22 +053084 EventProxy eventif.EventProxy
85 Client oop.OpenoltClient
86 cm *config.ConfigManager
87 device *voltha.Device
88 cfg *conf.AdapterFlags
89 coreClient *vgrpc.Client
90 childAdapterClients map[string]*vgrpc.Client
91 openOLT *OpenOLT
92 exitChannel chan struct{}
93 transitionMap *TransitionMap
94 clientCon *grpc.ClientConn
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070098
99 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530100
Akash Kankanala041a2122024-10-16 15:49:22 +0530101 portStats *OpenOltStatisticsMgr
102 metrics *pmmetrics.PmMetrics
103 stopCollector chan bool
104 stopHeartbeatCheck chan bool
105 stopIndications chan bool
106 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
107
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700108 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
109 // if the value is true that means the OnuDiscovery indication
110 // is currently being processed and thus we can ignore concurrent requests
111 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
112 // if we do it means something went wrong and we need to retry
Akash Kankanala041a2122024-10-16 15:49:22 +0530113 discOnus sync.Map
114 onus sync.Map
115 activePorts sync.Map
116 flowMgr []*OpenOltFlowMgr
117 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra491a9c62021-01-06 16:43:07 -0800118
119 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
120 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700121 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
122 stopMcastHandlerRoutine []chan bool
123 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000124
Akash Kankanala041a2122024-10-16 15:49:22 +0530125 lockChildAdapterClients sync.RWMutex
126 lockDevice sync.RWMutex
127 perPonOnuIndicationChannelLock sync.Mutex
128
129 totalPonPorts uint32
130 heartbeatSignature uint32
131 isCollectorActive bool
132 isHeartbeatCheckActive bool
133 isReadIndicationRoutineActive bool
134
Gamze Abakac2c32a62021-03-11 11:44:18 +0000135 adapterPreviouslyConnected bool
136 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700137
138 isDeviceDeletionInProgress bool
Nandita Biradar1b590f12024-09-27 10:56:28 +0530139 prevOperStatus common.OperStatus_Types
bseenivaaa9165b2025-09-18 17:28:12 +0530140 collectorWaitGroup sync.WaitGroup
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700141}
142
Mahir Gunyela2e68702022-12-07 00:00:42 -0800143// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700144type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400145 deviceID string
146 deviceType string
147 serialNumber string
Akash Kankanala041a2122024-10-16 15:49:22 +0530148 proxyDeviceID string
149 adapterEndpoint string
khenaidoo106c61a2021-08-11 18:05:46 -0400150 onuID uint32
151 intfID uint32
khenaidoo106c61a2021-08-11 18:05:46 -0400152 losRaised bool
153 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700154}
155
Mahir Gunyelb0046752021-02-26 13:51:05 -0800156type onuIndicationMsg struct {
157 ctx context.Context
158 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800159}
160
161type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800162 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800163 stopChannel chan struct{}
164}
165
Mahir Gunyela2e68702022-12-07 00:00:42 -0800166// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
167// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
168// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
169// and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800170type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400171 ctx context.Context // Flow/group handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400172 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
173 group *of.OfpGroupEntry // Group message (can be nil or valid group)
174 errChan *chan error // channel to report the mcast Flow/group handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530175 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
Girish Gowdra491a9c62021-01-06 16:43:07 -0800176}
177
Naga Manjunath7615e552019-10-11 22:35:47 +0530178var pmNames = []string{
179 "rx_bytes",
180 "rx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530181 "rx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530182 "rx_mcast_packets",
183 "rx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530184 "rx_error_packets",
185 "rx_crc_errors",
186 "rx_packets_dropped",
Naga Manjunath7615e552019-10-11 22:35:47 +0530187 "tx_bytes",
188 "tx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530189 "tx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530190 "tx_mcast_packets",
191 "tx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530192 "tx_error_packets",
193 "tx_dropped_total",
Naga Manjunath7615e552019-10-11 22:35:47 +0530194}
195
Mahir Gunyela2e68702022-12-07 00:00:42 -0800196// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400197func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700198 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700200 device.deviceType = deviceTp
201 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700202 device.onuID = onuID
203 device.intfID = intfID
204 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530205 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400206 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700207 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530208}
209
Mahir Gunyela2e68702022-12-07 00:00:42 -0800210// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400211func NewDeviceHandler(cc *vgrpc.Client, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager, cfg *conf.AdapterFlags) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700212 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530213 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800214 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400215 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400216 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700217 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 dh.device = cloned
219 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500220 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700221 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000222 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
223 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530224 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500225 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800226 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800227 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400228 dh.childAdapterClients = make(map[string]*vgrpc.Client)
229 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300230 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530231 if dh.kvStore == nil {
232 logger.Error(ctx, "Failed to setup KV store")
233 return nil
234 }
235
Girish Gowdra491a9c62021-01-06 16:43:07 -0800236 // Create a slice of buffered channels for handling concurrent mcast flow/group.
237 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700238 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
239 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800240 for i := range dh.incomingMcastFlowOrGroup {
241 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800242 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800243 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
244 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
245 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
246 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700247 dh.mcastHandlerRoutineActive[i] = true
248 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800249 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530250 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530252}
253
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530254func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
255 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
256 switch storeType {
257 case "etcd":
258 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530259 case "redis":
260 return kvstore.NewRedisClient(address, timeout, false)
261 case "redis-sentinel":
262 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530263 }
264 return nil, errors.New("unsupported-kv-store")
265}
266
267// SetKVClient sets the KV client and return a kv backend
268func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
269 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
270 if err != nil {
271 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
272 return nil
273 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530274 kvbackend := &db.Backend{
275 Client: kvClient,
276 StoreType: backend,
277 Address: addr,
278 Timeout: rsrcMgr.KvstoreTimeout,
279 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
280
281 return kvbackend
282}
283
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000284// CloseKVClient closes open KV clients
Abhay Kumarb87ac882025-10-30 09:55:07 +0000285// This method is thread-safe and can be called concurrently
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000286func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
Abhay Kumarb87ac882025-10-30 09:55:07 +0000287 // Acquire read lock to safely iterate over resourceMgr and flowMgr slices
288 // Use RLock since we're only reading the slices, not modifying them
289 dh.lockDevice.RLock()
290 defer dh.lockDevice.RUnlock()
291
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000292 if dh.resourceMgr != nil {
293 for _, rscMgr := range dh.resourceMgr {
294 if rscMgr != nil {
295 rscMgr.CloseKVClient(ctx)
296 }
297 }
298 }
299 if dh.flowMgr != nil {
300 for _, flMgr := range dh.flowMgr {
301 if flMgr != nil {
302 flMgr.CloseKVClient(ctx)
303 }
304 }
305 }
306}
307
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308// start save the device to the data model
309func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700310 dh.lockDevice.Lock()
311 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700313 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000314 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530315}
316
khenaidooefff76e2021-12-15 16:51:30 -0500317// Stop stops the device handler
318func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700319 dh.lockDevice.Lock()
320 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500322 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400323
khenaidooefff76e2021-12-15 16:51:30 -0500324 // Delete (which will stop also) all grpc connections to the child adapters
325 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000326 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530327}
328
ssiddiqui04386ee2021-08-23 21:58:25 +0530329func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
330 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
331 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
332 if pooledIntfID == intfID {
333 return resourceRanges.GetTechnology()
334 }
335 }
336 }
337 return ""
338}
339
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400340func macifyIP(ip net.IP) string {
341 if len(ip) > 0 {
342 oct1 := strconv.FormatInt(int64(ip[12]), 16)
343 oct2 := strconv.FormatInt(int64(ip[13]), 16)
344 oct3 := strconv.FormatInt(int64(ip[14]), 16)
345 oct4 := strconv.FormatInt(int64(ip[15]), 16)
346 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
347 }
348 return ""
349}
350
Neha Sharma96b7bf22020-06-15 10:37:32 +0000351func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400352 var genmac string
353 var addr net.IP
354 var ips []string
355 var err error
356
Neha Sharma96b7bf22020-06-15 10:37:32 +0000357 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400358
359 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000360 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400361
362 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000363 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400364 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000365 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400366 }
367 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000368 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530369 log.Fields{"host": ips[0],
370 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400371 return genmac, nil
372 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000373 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400374 }
375
376 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000377 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530378 log.Fields{"host": host,
379 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400380 return genmac, nil
381}
382
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530383func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700384 slist := strings.Split(mac, ":")
385 result := make([]uint32, len(slist))
386 var err error
387 var tmp int64
388 for index, val := range slist {
389 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
390 return []uint32{1, 2, 3, 4, 5, 6}
391 }
392 result[index] = uint32(tmp)
393 }
394 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530395}
396
Mahir Gunyela2e68702022-12-07 00:00:42 -0800397// GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800398func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800399 switch portType {
400 case voltha.Port_ETHERNET_NNI:
401 return fmt.Sprintf("nni-%d", portNum), nil
402 case voltha.Port_PON_OLT:
403 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700404 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800405
Girish Kumarf26e4882020-03-05 06:49:10 +0000406 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530407}
408
Elia Battiston596406d2022-02-02 12:19:00 +0100409func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
410 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530411 // In case it was not set in the indication
412 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100413 speedMbps = defaultPortSpeedMbps
414 }
415
416 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
417 switch speedMbps {
418 case 1000000:
419 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
420 case 100000:
421 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
422 case 40000:
423 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
424 case 10000:
425 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
426 case 1000:
427 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
428 case 100:
429 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
430 case 10:
431 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
432 }
433
434 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
435
436 port := &of.OfpPort{
437 HwAddr: macAddressToUint32Array(macAddress),
438 Config: 0,
439 State: uint32(of.OfpPortState_OFPPS_LIVE),
440 Curr: capacity,
441 Advertised: capacity,
442 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530443 CurrSpeed: speedMbps * 1000, // kbps
444 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100445 }
446
447 return port
448}
449
450func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000451 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 if state == "up" {
453 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530454 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500455 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700456 } else {
457 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500458 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700459 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700460 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400461 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000463 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400464 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500465
khenaidoo106c61a2021-08-11 18:05:46 -0400466 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400467 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400468 DeviceId: dh.device.Id,
469 Port: portNum,
470 })
471 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000472 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400473 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400474 DeviceId: dh.device.Id,
475 PortType: portType,
476 PortNo: portNum,
477 OperStatus: operStatus})
478 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400479 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
480 "device-id": dh.device.Id,
481 "port-type": portType,
482 "port-number": portNum,
483 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500484 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400485 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500486 }
khenaidoo106c61a2021-08-11 18:05:46 -0400487
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400488 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400489 port = &voltha.Port{
490 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700491 PortNo: portNum,
492 Label: label,
493 Type: portType,
494 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100495 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700496 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700498 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400499 err = dh.createPortInCore(ctx, port)
500 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000501 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800502 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000503 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400504 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000505 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530506 return nil
507}
508
Kent Hagermane6ff1012020-07-14 15:07:53 -0400509func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400510 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530511 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400512 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
513 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530514 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800515 dh.lockDevice.Lock()
516 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530517 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530518}
519
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700520// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530521// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800522func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000523 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700524 defer func() {
525 dh.lockDevice.Lock()
526 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530527 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700528 dh.lockDevice.Unlock()
529 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700530 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700531 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700532 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700533 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400534
David Bainbridgef5879ca2019-12-13 21:17:54 +0000535 // Create an exponential backoff around re-enabling indications. The
536 // maximum elapsed time for the back off is set to 0 so that we will
537 // continue to retry. The max interval defaults to 1m, but is set
538 // here for code clarity
539 indicationBackoff := backoff.NewExponentialBackOff()
540 indicationBackoff.MaxElapsedTime = 0
541 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700542
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700543 dh.lockDevice.Lock()
544 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530545 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700546 dh.lockDevice.Unlock()
547
Girish Gowdra3f974912020-03-23 20:35:18 -0700548Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700549 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400550 select {
551 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000552 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700553 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400554 default:
555 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100556
557 select {
558 case <-indications.Context().Done():
559 if err != nil {
560 logger.Warnw(ctx, "error-during-enable-indications",
561 log.Fields{"err": err,
562 "device-id": dh.device.Id})
563 }
564
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400565 // Use an exponential back off to prevent getting into a tight loop
566 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100567 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
568 "device-id": dh.device.Id,
569 "duration": duration,
570 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400571 if duration == backoff.Stop {
572 // If we reach a maximum then warn and reset the backoff
573 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100574 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530575 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530576 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400577 indicationBackoff.Reset()
578 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700579
580 // On failure process a backoff timer while watching for stopIndications
581 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700582 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700583 select {
584 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000585 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700586 if !backoffTimer.Stop() {
587 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700588 }
589 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700590 case <-backoffTimer.C:
591 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700592 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700593 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
594 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400595 }
596 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100597 default:
598 if err != nil {
599 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530600 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530601 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100602 // Close the stream, and re-initialize it
603 if err = indications.CloseSend(); err != nil {
604 // Ok to ignore here, because we landed here due to a problem on the stream
605 // In all probability, the closeSend call may fail
606 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
607 log.Fields{"err": err,
608 "device-id": dh.device.Id})
609 }
610 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
611 return err
612 }
613 // once we re-initialized the indication stream, continue to read indications
614 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700615 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100616 // Reset backoff if we have a successful receive
617 indicationBackoff.Reset()
618 // When OLT is admin down, ignore all indications.
619 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
620 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
621 log.Fields{"indication": indication,
622 "device-id": dh.device.Id})
623 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700624 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100625 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530626 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700627 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700629 // Close the send stream
630 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700631
Girish Gowdra3f974912020-03-23 20:35:18 -0700632 return nil
633}
634
635func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700636 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700637 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
638 if err != nil {
639 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
640 }
641 if indications == nil {
642 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
643 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700644 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700645 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400646}
647
648// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
649func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
650 switch indication.Data.(type) {
651 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
652 return true
653
654 default:
655 return false
656 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657}
658
David K. Bainbridge794735f2020-02-11 21:01:37 -0800659func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700660 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000661 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530662 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700663 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530664 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000666 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000667 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530668 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000669 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800670 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000671 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800672 }
673 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674}
675
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530676func (dh *DeviceHandler) handleOnuDisableIndication(ctx context.Context, onuIndication *oop.OnuDisabledIndication) error {
677 logger.Infow(ctx, "handleOnuDisableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
678 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
679 intfID := onuIndication.GetIntfId()
680 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
681 onuDev := dh.getChildDevice(ctx, sn, ponPort)
682 if onuDev == nil {
683 logger.Warnw(ctx, "handleOnuDisableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
684 onuDev = &OnuDevice{
685 serialNumber: sn,
686 }
687 }
688 dh.discOnus.Delete(sn)
689
690 raisedTs := time.Now().Unix()
691 if err := dh.eventMgr.onuDisableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
692 return olterrors.NewErrAdapter("failed-indication", log.Fields{
693 "device-id": dh.device.Id,
694 "indication": onuIndication,
695 "timestamp": raisedTs}, err)
696 }
697 OnuIndication := generateOnuIndication(onuDev.intfID, onuDev.onuID, "down", "down")
698 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDev.adapterEndpoint, &ia.OnuIndicationMessage{
699 DeviceId: onuDev.deviceID,
700 OnuIndication: OnuIndication.GetOnuInd(),
701 })
702 if err != nil {
703 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
704 "onu-indicator": OnuIndication.GetOnuInd(),
705 "source": dh.openOLT.config.AdapterEndpoint,
706 "device-type": onuDev.deviceType,
707 "device-id": onuDev.deviceID}, err)
708 }
709 return nil
710}
711
712func (dh *DeviceHandler) handleOnuEnableIndication(ctx context.Context, onuIndication *oop.OnuEnabledIndication) error {
713 logger.Infow(ctx, "handleOnuEnableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
714 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
715 intfID := onuIndication.GetIntfId()
716 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
717 onuDev := dh.getChildDevice(ctx, sn, ponPort)
718 if onuDev == nil {
719 logger.Warnw(ctx, "handleOnuEnableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
720 onuDev = &OnuDevice{
721 serialNumber: sn,
722 }
723 }
724 raisedTs := time.Now().Unix()
725
726 if err := dh.eventMgr.onuEnableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
727 return olterrors.NewErrAdapter("failed-indication", log.Fields{
728 "device-id": dh.device.Id,
729 "indication": onuIndication,
730 "timestamp": raisedTs}, err)
731 }
732 return nil
733}
734
Akash Kankanala041a2122024-10-16 15:49:22 +0530735// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530736func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700737 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700738 switch indication.Data.(type) {
739 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000740 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
741 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700742 logger.Infow(ctx, "received olt indication", log.Fields{"device-id": dh.device.Id, "olt-ind": indication.GetOltInd()})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800743 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400744 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800745 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700746 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000747 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
748 defer span.Finish()
749
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700750 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800751 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100752 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400753 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800754 }
755 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000756 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700757 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000758 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
759 defer span.Finish()
760
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 intfOperInd := indication.GetIntfOperInd()
762 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800763 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100764 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400765 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800766 }
767 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 } else if intfOperInd.GetType() == "pon" {
769 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
770 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800771 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100772 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400773 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800774 }
775 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000776 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700777 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000778 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530779 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530780 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000782 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
783 defer span.Finish()
784
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700785 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000786 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530787 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800788 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700789 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000790 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
791 defer span.Finish()
792
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700793 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000794 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530795 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800796 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700797 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000798 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
799 defer span.Finish()
800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000802 logger.Debugw(ctx, "received-omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800803 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000804 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400805 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800806 }
807 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700808 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000809 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
810 defer span.Finish()
811
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700812 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000813 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700814 "intf-type": pktInd.IntfId,
815 "intf-id": pktInd.IntfId,
816 "gem-port-id": pktInd.GemportId,
817 "port-no": pktInd.PortNo,
818 "device-id": dh.device.Id,
819 })
820
821 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000822 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700823 "intf-type": pktInd.IntfId,
824 "intf-id": pktInd.IntfId,
825 "gem-port-id": pktInd.GemportId,
826 "port-no": pktInd.PortNo,
827 "packet": hex.EncodeToString(pktInd.Pkt),
828 "device-id": dh.device.Id,
829 })
830 }
831
David K. Bainbridge794735f2020-02-11 21:01:37 -0800832 go func() {
833 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400834 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800835 }
836 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000838 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
839 defer span.Finish()
840
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700841 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700842 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700843 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000844 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
845 defer span.Finish()
846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000848 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700849 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000850 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
851 defer span.Finish()
852
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700853 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000854 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
855 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530856 case *oop.Indication_OnuDisabledInd:
857 span, ctx := log.CreateChildSpan(ctx, "onu-disable-indication", log.Fields{"device-id": dh.device.Id})
858 defer span.Finish()
859 logger.Infow(ctx, "received onu-disable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
860 if err := dh.handleOnuDisableIndication(ctx, indication.GetOnuDisabledInd()); err != nil {
861 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
862 }
863 case *oop.Indication_OnuEnabledInd:
864 span, ctx := log.CreateChildSpan(ctx, "onu-enable-indication", log.Fields{"device-id": dh.device.Id})
865 defer span.Finish()
866 logger.Infow(ctx, "received onu-enable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
867 if err := dh.handleOnuEnableIndication(ctx, indication.GetOnuEnabledInd()); err != nil {
868 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
869 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700870 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530871}
872
nikesh.krishnanc8473432023-06-14 12:14:54 +0530873func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
874 onuInd := &oop.OnuIndication{
875 IntfId: intfID,
876 OnuId: onuID,
877 OperState: operState,
878 AdminState: adminState,
879 }
880 indication := &oop.Indication{
881 Data: &oop.Indication_OnuInd{
882 OnuInd: onuInd,
883 },
884 }
885 return indication
886}
887
888func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
889 onuAlarmInd := &oop.OnuAlarmIndication{
890 IntfId: intfID,
891 OnuId: onuID,
892 LosStatus: losStatus,
893 }
894 alarmInd := &oop.AlarmIndication{
895 Data: &oop.AlarmIndication_OnuAlarmInd{
896 OnuAlarmInd: onuAlarmInd,
897 },
898 }
899 return alarmInd
900}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530901
Akash Kankanala041a2122024-10-16 15:49:22 +0530902func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530903 ponlosAlarmInd := &oop.LosIndication{
904 IntfId: intfID,
905 Status: losStatus,
906 }
907 alarmInd := &oop.AlarmIndication{
908 Data: &oop.AlarmIndication_LosInd{
909 LosInd: ponlosAlarmInd,
910 },
911 }
912 return alarmInd
913}
Akash Kankanala041a2122024-10-16 15:49:22 +0530914
nikesh.krishnanc8473432023-06-14 12:14:54 +0530915func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
916 go func() {
917 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
918 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
919 }
920 }()
921
922 raisedTs := time.Now().Unix()
923 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
924}
925
926func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530927 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
928 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530929 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530930 return err
931 }
932 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530933 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
934 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
935 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
936
937 onuID := onuDeviceFromCore.ProxyAddress.OnuId
938 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
939 if err != nil {
940 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530941 } else {
942 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
943 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
944 switch {
945 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
946 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
947 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
948
949 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530950 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530951 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
952 raisedTs := time.Now().Unix()
953 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
954
955 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
956 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530957 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530958 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530959 return nil
960}
961
962func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
963 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
964 DeviceId: dh.device.Id,
965 PortType: voltha.Port_PON_OLT,
966 })
967 if err != nil {
968 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530969 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530970 }
971 for _, portFromCore := range portsFromCore.Items {
972 portNum := portFromCore.GetPortNo()
973 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
974 portOperStatusFromCore := portFromCore.OperStatus
975 portAdminStateFromCore := portFromCore.AdminState
976 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
977 if err != nil {
978 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
979 } else {
980 portLosFromOlt := ponPortFromOlt.GetLos()
981 portStateFromOlt := ponPortFromOlt.GetState()
982 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
983 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
984 "portStateFromOlt": portStateFromOlt.String(),
985 "portOperStatusFromCore": portOperStatusFromCore.String(),
986 "device-id": dh.device.Id,
987 "port": portNum})
988 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
989 raisedTs := time.Now().Unix()
990 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530991 }
992 switch {
993 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
994 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
995 "portStateFromOlt": portStateFromOlt.String(),
996 "portOperStatusFromCore": portOperStatusFromCore.String(),
997 "device-id": dh.device.Id,
998 "port": portNum})
999 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
1000 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
1001 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
1002 "portStateFromOlt": portStateFromOlt.String(),
1003 "portOperStatusFromCore": portOperStatusFromCore.String(),
1004 "device-id": dh.device.Id,
1005 "port": portNum})
1006 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
1007 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
1008 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
1009 "device-id": dh.device.Id,
1010 "port": portNum})
1011 default:
1012 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
1013 "portStateFromOlt": portStateFromOlt.String(),
1014 "portOperStatusFromCore": portOperStatusFromCore.String(),
1015 "device-id": dh.device.Id,
1016 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301017 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301018 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301019 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301020 return nil
1021}
1022
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301023// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301024func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +05301025 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +05301026 // Declare deviceStateFilter to be used later
1027 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +05301028 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001029 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +05301030 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301031 if err != nil {
1032 return fmt.Errorf("failed to get device from core: %w", err)
1033 }
1034 logger.Info(ctx, "Device state", log.Fields{
1035 "device-id": device.Id,
1036 "CurrOperStatus": device.OperStatus,
1037 "CurrConnStatus": device.ConnectStatus,
1038 })
1039 // Perform cleanup if the device's operational status is REBOOTED
1040 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
1041 // Log the device's operational status if it's REBOOTED
1042 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
1043 "device-id": device.Id,
1044 "OperStatus": device.OperStatus,
1045 })
1046 dh.lockDevice.RLock()
1047 // Stop the read indication only if it the routine is active
1048 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1049 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1050 // on next execution of the readIndication routine.
1051 if dh.isHeartbeatCheckActive {
1052 dh.stopHeartbeatCheck <- true
1053 }
1054 if dh.isReadIndicationRoutineActive {
1055 dh.stopIndications <- true
1056 }
bseenivaaa9165b2025-09-18 17:28:12 +05301057 if dh.isCollectorActive {
1058 dh.stopCollector <- true
1059 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301060 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +05301061 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301062 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
1063 return fmt.Errorf("cleanup device resources failed: %w", err)
1064 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301065 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301066 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1067 }
bseenivaaa9165b2025-09-18 17:28:12 +05301068 dh.collectorWaitGroup.Add(1)
1069 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301070 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301071 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +05301072 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
1073 // Log the device's operational status if it's RECONCILING
1074 logger.Info(ctx, "Device is being reconciled", log.Fields{
1075 "device-id": device.Id,
1076 "OperStatus": device.OperStatus,
1077 })
1078
1079 // Perform reconciliation steps
1080 err = dh.reconcileOnus(ctx)
1081 if err != nil {
1082 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1083 }
1084 err = dh.reconcilePonPorts(ctx)
1085 if err != nil {
1086 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301087 }
1088 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001089 // instantiate the mcast handler routines.
1090 for i := range dh.incomingMcastFlowOrGroup {
1091 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1092 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1093 if !dh.mcastHandlerRoutineActive[i] {
1094 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1095 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1096 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1097 // for incoming mcast flow/group to be processed serially.
1098 dh.mcastHandlerRoutineActive[i] = true
1099 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1100 }
1101 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301102 // Create DeviceStateFilter with the desired operational and connection statuses
1103 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001104 DeviceId: dh.device.Id,
1105 OperStatus: voltha.OperStatus_ACTIVE,
1106 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301107 }
1108 // Log DeviceStateFilter for debugging purposes
1109 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1110 "DeviceId": deviceStateFilter.DeviceId,
1111 "OperStatus": deviceStateFilter.OperStatus,
1112 "ConnStatus": deviceStateFilter.ConnStatus,
1113 })
1114 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301115 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001116 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001117 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001118
Akash Kankanala041a2122024-10-16 15:49:22 +05301119 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001120 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1121 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301122
1123 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1124 if err != nil {
1125 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1126 }
1127 dh.populateActivePorts(ctx, ports.Items)
1128 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1129 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1130 }
1131
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001132 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001133 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1134
Girish Gowdru0c588b22019-04-23 23:24:56 -04001135 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301136}
1137
1138// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301139func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001140 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001141
khenaidoo106c61a2021-08-11 18:05:46 -04001142 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001143 if err != nil || device == nil {
1144 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001145 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001146 }
1147
1148 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001149
Akash Kankanala041a2122024-10-16 15:49:22 +05301150 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001151 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001152 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001153 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001154 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001155
khenaidoodc2116e2021-10-19 17:33:19 -04001156 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001157 DeviceId: cloned.Id,
1158 OperStatus: cloned.OperStatus,
1159 ConnStatus: cloned.ConnectStatus,
1160 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001161 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001162 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001163
Akash Kankanala041a2122024-10-16 15:49:22 +05301164 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001165 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001166 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001167 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001168 }
1169 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001170 // Update onu state as down in onu adapter
1171 onuInd := oop.OnuIndication{}
1172 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001173
1174 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1175 if err != nil {
1176 return err
1177 }
1178 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001179 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001180 DeviceId: onuDevice.Id,
1181 OnuIndication: &onuInd,
1182 })
1183 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001184 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001185 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001186 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 "onu-indicator": onuInd,
1188 "device-type": onuDevice.Type,
1189 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301190 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001191 } else {
1192 logger.Debugw(ctx, "sending inter adapter down ind to onu success", log.Fields{"olt-device-id": device.Id, "onu-device-id": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001194 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001195 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001196 /* Discovered ONUs entries need to be cleared , since after OLT
1197 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301198 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001199 dh.lockDevice.Unlock()
1200
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001202 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301203}
1204
1205// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301206func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001207 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001208
1209 // if the connection is already available, close the previous connection (olt reboot case)
1210 if dh.clientCon != nil {
1211 if err = dh.clientCon.Close(); err != nil {
1212 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1213 } else {
1214 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1215 }
1216 }
1217
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301218 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Abhay Kumard3f18512025-12-09 07:51:12 +00001219 grpc_prometheus.EnableClientHandlingTimeHistogram()
Gamze Abaka49c40b32021-05-06 09:30:41 +00001220 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001221 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1222 grpc.WithInsecure(),
1223 grpc.WithBlock(),
1224 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001225 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001226 grpc_prometheus.StreamClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001227 )),
1228 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001229 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Abhay Kumard3f18512025-12-09 07:51:12 +00001230 grpc_prometheus.UnaryClientInterceptor,
Girish Kumar93e91742020-07-27 16:43:19 +00001231 )))
1232
1233 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301234 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301235 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001236 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001237 }
Akash Sonif49299a2024-04-25 12:06:37 +05301238 //Setting oper and connection state to RECONCILING and conn state to reachable
1239 cgClient, err := dh.coreClient.GetCoreServiceClient()
1240 if err != nil {
1241 return err
1242 }
1243
1244 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1245 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1246 defer cancel()
1247 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1248 DeviceId: dh.device.Id,
1249 OperStatus: voltha.OperStatus_RECONCILING,
1250 ConnStatus: voltha.ConnectStatus_REACHABLE,
1251 }); err != nil {
1252 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1253 }
1254 // The OperState and connection state of the device is set to RECONCILING and REACHABLE in the previous section. This also needs to be set on the
1255 // locally cached copy of the device struct.
1256 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1257 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1258 }
1259
Girish Gowdru0c588b22019-04-23 23:24:56 -04001260 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301261}
1262
1263// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301264func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001265 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301266 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001267 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301268}
1269
1270// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301271func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301272 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001273 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001274
1275 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001276 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301277 if err != nil || device == nil {
1278 /*TODO: needs to handle error scenarios */
1279 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1280 }
1281 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001282 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001283
1284 cloned := proto.Clone(device).(*voltha.Device)
1285 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1286 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1287 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001288
khenaidoodc2116e2021-10-19 17:33:19 -04001289 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001290 DeviceId: cloned.Id,
1291 OperStatus: cloned.OperStatus,
1292 ConnStatus: cloned.ConnectStatus,
1293 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301294 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001295 }
1296
Chaitrashree G S44124192019-08-07 20:21:36 -04001297 // 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 +05301298 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001299 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301300 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001301 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001302 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1303 // all the modules initialized and ready to handle incoming ONUs.
1304
Thomas Lee S985938d2020-05-04 11:40:41 +05301305 err = dh.initializeDeviceHandlerModules(ctx)
1306 if err != nil {
1307 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 -04001308 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001309
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001310 go startHeartbeatCheck(ctx, dh)
1311
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001312 return nil
1313 }
1314
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001315 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301316 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 -04001317 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301318
Neha Sharma96b7bf22020-06-15 10:37:32 +00001319 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001320
1321 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001323 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001324
1325 go startHeartbeatCheck(ctx, dh)
1326
cuilin20187b2a8c32019-03-26 19:52:28 -07001327 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301328}
1329
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001330func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001331 var err error
1332 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001333
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001334 if dh.flowMgr != nil {
1335 dh.StopAllFlowRoutines(ctx)
1336 }
1337
1338 dh.CloseKVClient(ctx)
1339
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001340 if err != nil {
1341 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1342 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001343 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1344 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301345 // If collector go routine is active, wait for it to stop
1346 dh.lockDevice.RLock()
1347 if dh.isCollectorActive {
1348 dh.lockDevice.RUnlock()
1349 dh.collectorWaitGroup.Wait()
1350 } else {
1351 dh.lockDevice.RUnlock()
1352 }
yasin saplid0566272021-12-21 09:10:30 +00001353 // +1 is for NNI
1354 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1355 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001356 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001357 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1358 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1359 // There is only one NNI manager since multiple NNI is not supported for now
1360 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001361 // Instantiate resource manager
1362 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 -07001363 return olterrors.ErrResourceManagerInstantiating
1364 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001365 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001366 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1367 // the KV store to manage mcast group data. Provide the first instance (0th index)
1368 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1369 return olterrors.ErrGroupManagerInstantiating
1370 }
yasin saplid0566272021-12-21 09:10:30 +00001371 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001372 // Instantiate flow manager
1373 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301374 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001375 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1376 } else {
1377 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001378 }
1379 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001380 /* TODO: Instantiate Alarm , stats , BW managers */
1381 /* Instantiating Event Manager to handle Alarms and KPIs */
1382 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1383
1384 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001385 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001386
1387 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001388}
1389
Neha Sharma96b7bf22020-06-15 10:37:32 +00001390func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001391 var err error
1392 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301393 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001394
Neha Sharma8f4e4322020-08-06 10:51:53 +00001395 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001396
1397 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001398 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001399 }
1400 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001401 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001402 }
1403
Neha Sharma96b7bf22020-06-15 10:37:32 +00001404 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001405 dh.device.Root = true
1406 dh.device.Vendor = deviceInfo.Vendor
1407 dh.device.Model = deviceInfo.Model
1408 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1409 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1410 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1411
1412 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001413 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001414 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301415 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001416 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001417 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001418 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001419 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001420 dh.device.MacAddress = genmac
1421 } else {
1422 dh.device.MacAddress = deviceInfo.DeviceId
1423 }
1424
1425 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001426 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001427 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001428 }
1429
1430 return deviceInfo, nil
1431}
1432
Neha Sharma96b7bf22020-06-15 10:37:32 +00001433func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301434 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001435
1436 defer func() {
1437 dh.lockDevice.Lock()
1438 dh.isCollectorActive = false
1439 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301440 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001441 }()
1442
1443 dh.lockDevice.Lock()
1444 dh.isCollectorActive = true
1445 dh.lockDevice.Unlock()
1446
Naga Manjunath7615e552019-10-11 22:35:47 +05301447 for {
1448 select {
1449 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301450 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301451 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001452 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001453
khenaidoo106c61a2021-08-11 18:05:46 -04001454 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001455 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001456 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001457 continue
1458 }
khenaidoo106c61a2021-08-11 18:05:46 -04001459 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301460 // NNI Stats
1461 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001462 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301463 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001464 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001465 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001466 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301467 }
1468 // PON Stats
1469 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001470 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301471 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1472 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001473 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001474 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301475 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001476 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001477
yasin sapli9e4c5092022-02-01 13:52:33 +00001478 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001479 if len(onuGemInfoLst) > 0 {
1480 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001481 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001482 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301483 }
1484 }
1485 }
1486}
1487
Mahir Gunyela2e68702022-12-07 00:00:42 -08001488// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301489func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001490 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001491 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301492 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301493
1494 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001495 cgClient, err := dh.coreClient.GetCoreServiceClient()
1496 if err != nil {
1497 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1498 return
1499 }
1500
1501 // Now, set the initial PM configuration for that device
1502 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001503 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301504 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301505}
1506
Mahir Gunyela2e68702022-12-07 00:00:42 -08001507// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001508func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1509 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001510 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301511 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001512 HwDesc: "open_pon",
1513 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001514 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001515 },
1516 SwitchFeatures: &of.OfpSwitchFeatures{
1517 NBuffers: 256,
1518 NTables: 2,
1519 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1520 of.OfpCapabilities_OFPC_TABLE_STATS |
1521 of.OfpCapabilities_OFPC_PORT_STATS |
1522 of.OfpCapabilities_OFPC_GROUP_STATS),
1523 },
1524 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301525}
1526
khenaidoo106c61a2021-08-11 18:05:46 -04001527// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001528func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001529 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001530 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001531 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001532 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001533 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1534 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()
1535 }
khenaidoo106c61a2021-08-11 18:05:46 -04001536 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001537}
1538
Neha Sharma96b7bf22020-06-15 10:37:32 +00001539func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001540 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 -07001541 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001542 var deviceID string
1543 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001544 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001545
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001546 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001547 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001548 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 -07001549 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1550 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001551
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001552 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301553
1554 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555 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 -07001556 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001557
khenaidoodc2116e2021-10-19 17:33:19 -04001558 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001559 ParentId: dh.device.Id,
1560 OnuId: omciInd.OnuId,
1561 ParentPortNo: ponPort,
1562 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001563 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301564 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001565 "intf-id": omciInd.IntfId,
1566 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001567 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001568 deviceType = onuDevice.Type
1569 deviceID = onuDevice.Id
1570 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001571 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301572 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001573 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001574 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301575 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001576 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 +05301577 deviceType = onuInCache.(*OnuDevice).deviceType
1578 deviceID = onuInCache.(*OnuDevice).deviceID
1579 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001580 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001581 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001582
khenaidoodc2116e2021-10-19 17:33:19 -04001583 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001584 ParentDeviceId: proxyDeviceID,
1585 ChildDeviceId: deviceID,
1586 Message: omciInd.Pkt,
1587 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301588 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001589 "source": dh.openOLT.config.AdapterEndpoint,
1590 "device-type": deviceType,
1591 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001592 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001593 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001594 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001595 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301596}
1597
khenaidoo106c61a2021-08-11 18:05:46 -04001598// //ProcessInterAdapterMessage sends the proxied messages to the target device
1599// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1600// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001601// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001602// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001603// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001604// return dh.handleInterAdapterOmciMsg(ctx, msg)
1605// }
1606// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1607// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001608
kesavandb9f54fd2021-11-25 20:08:04 +05301609// ProxyOmciRequests sends the proxied OMCI message to the target device
1610func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301611 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1612 return status.Error(codes.Unavailable, "OLT unreachable")
1613 }
kesavandb9f54fd2021-11-25 20:08:04 +05301614 if omciMsgs.GetProxyAddress() == nil {
1615 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1616 if err != nil {
1617 return olterrors.NewErrNotFound("onu", log.Fields{
1618 "parent-device-id": dh.device.Id,
1619 "child-device-id": omciMsgs.ChildDeviceId}, err)
1620 }
1621 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1622 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1623 return olterrors.NewErrCommunication("send-failed", log.Fields{
1624 "parent-device-id": dh.device.Id,
1625 "child-device-id": omciMsgs.ChildDeviceId}, err)
1626 }
1627 } else {
1628 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1629 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1630 return olterrors.NewErrCommunication("send-failed", log.Fields{
1631 "parent-device-id": dh.device.Id,
1632 "child-device-id": omciMsgs.ChildDeviceId}, err)
1633 }
1634 }
1635 return nil
1636}
1637
1638func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1639 var intfID uint32
1640 var onuID uint32
1641 var connectStatus common.ConnectStatus_Types
1642 if onuDevice != nil {
1643 intfID = onuDevice.ProxyAddress.GetChannelId()
1644 onuID = onuDevice.ProxyAddress.GetOnuId()
1645 connectStatus = onuDevice.ConnectStatus
1646 } else {
1647 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1648 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1649 connectStatus = omciMsgs.GetConnectStatus()
1650 }
1651 if connectStatus != voltha.ConnectStatus_REACHABLE {
1652 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1653
1654 return olterrors.NewErrCommunication("unreachable", log.Fields{
1655 "intf-id": intfID,
1656 "onu-id": onuID}, nil)
1657 }
1658
1659 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1660 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1661
1662 onuSecOmciMsgList := omciMsgs.GetMessages()
1663
1664 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301665 var omciMessage *oop.OmciMsg
1666 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1667 hex.Encode(hexPkt, onuSecOmciMsg)
1668 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1669
1670 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1671 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1672 //https://jira.opencord.org/browse/VOL-4604
1673 transid := extractOmciTransactionID(onuSecOmciMsg)
1674 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1675 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1676
1677 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1678 if err != nil {
1679 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1680 "intf-id": intfID,
1681 "onu-id": onuID,
1682 "message": omciMessage}, err)
1683 }
1684 }
1685 return nil
1686}
1687
khenaidoo106c61a2021-08-11 18:05:46 -04001688// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001689func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001690 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 -07001691
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301692 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1693 return status.Error(codes.Unavailable, "OLT unreachable")
1694 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001695 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001696 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001697 if err != nil {
1698 return olterrors.NewErrNotFound("onu", 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 }
khenaidoo106c61a2021-08-11 18:05:46 -04001702 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1703 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001704 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001705 "parent-device-id": dh.device.Id,
1706 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001707 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001708 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001709 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1710 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001711 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001712 "parent-device-id": dh.device.Id,
1713 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001714 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001715 }
1716 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301717}
1718
khenaidoodc2116e2021-10-19 17:33:19 -04001719func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001720 var intfID uint32
1721 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001722 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001723 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001724 intfID = onuDevice.ProxyAddress.GetChannelId()
1725 onuID = onuDevice.ProxyAddress.GetOnuId()
1726 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001727 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001728 intfID = omciMsg.GetProxyAddress().GetChannelId()
1729 onuID = omciMsg.GetProxyAddress().GetOnuId()
1730 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001731 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001732 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001733 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 -08001734
Thomas Lee S94109f12020-03-03 16:39:29 +05301735 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001736 "intf-id": intfID,
1737 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001738 }
1739
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001740 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1741 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301742 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001743 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001744 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1745 hex.Encode(hexPkt, omciMsg.Message)
1746 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1747
1748 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1749 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1750 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001751 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001752 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001753
Neha Sharma8f4e4322020-08-06 10:51:53 +00001754 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001755 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301756 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001757 "intf-id": intfID,
1758 "onu-id": onuID,
1759 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001760 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001761 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001762}
1763
David K. Bainbridge794735f2020-02-11 21:01:37 -08001764func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301765 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 +00001766 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001767 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001768 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001769 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301770 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301771 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001772 st, _ := status.FromError(err)
1773 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774 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 -04001775 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301776 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001777 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001778 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001780 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001781 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001782}
1783
Mahir Gunyela2e68702022-12-07 00:00:42 -08001784// getChildDevice function can be used in general to get child device, if not found in cache the function will
1785// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301786func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1787 var InCacheOnuDev *OnuDevice
1788 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1789 if onuInCache.(*OnuDevice).serialNumber == sn {
1790 InCacheOnuDev = onuInCache.(*OnuDevice)
1791 return false
1792 }
1793 return true
1794 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301795 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301796 if InCacheOnuDev != nil {
1797 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1798 return InCacheOnuDev
1799 }
1800 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1801 ParentId: dh.device.Id,
1802 SerialNumber: sn,
1803 ParentPortNo: parentPortNo,
1804 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301805 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301806 if onuDevice == nil {
1807 return nil
1808 }
1809 onuID := onuDevice.ProxyAddress.OnuId
1810 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1811 onuKey := dh.formOnuKey(intfID, onuID)
1812
1813 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1814 dh.onus.Store(onuKey, onuDev)
1815 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1816 return onuDev
1817}
1818
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301819// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1820// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301821func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001822 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301823 // 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 +05301824 // 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 +05301825 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1826 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1827 ParentId: dh.device.Id,
1828 SerialNumber: sn,
1829 ParentPortNo: parentPortNo,
1830 })
1831 if onuDevice != nil {
1832 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1833 return true, nil
1834 }
1835 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1836
1837 return false, nil
1838 } else {
1839 tpInstExists := false
1840 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301841 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1842 if onuDev != nil {
1843 var onuGemInfo *rsrcMgr.OnuGemInfo
1844 var err error
1845 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1846 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1847 return false, err
1848 }
1849 if onuGemInfo != nil {
1850 for _, uni := range onuGemInfo.UniPorts {
1851 uniID := plt.UniIDFromPortNum(uni)
1852 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1853 if len(tpIDs) != 0 {
1854 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1855 tpInstExists = true
1856 break
1857 }
1858 }
1859 }
1860 }
1861 return tpInstExists, nil
1862 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301863}
1864
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001865// processDiscONULOSClear clears the LOS Alarm if it's needed
1866func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301867 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001868 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301869
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001870 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1871 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1872 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1873 OnuLosRaise event sent for it */
1874 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1875 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1876 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1877 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1878 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1879 "currentIntfId": onuDiscInd.GetIntfId()})
1880 // TODO:: Should we need to ignore raising OnuLosClear event
1881 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301882 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001883 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1884 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1885 alarmInd.LosStatus = statusCheckOff
1886 go func() {
1887 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1888 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1889 }
1890 }()
1891 // stop iterating
1892 return false
1893 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301894 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001895 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301896}
1897
bseeniva43b5a912025-06-05 12:48:15 +05301898func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1899 if err != nil || tpInstExists {
1900 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1901 } else {
1902 // once the function completes set the value to false so that
1903 // we know the processing has inProcess.
1904 // Note that this is done after checking if we are already processing
1905 // to avoid changing the value from a different thread
1906 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1907 dh.discOnus.Store(sn, false)
1908 }
1909}
1910
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301911func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301912 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301913 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301914
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301915 channelID := onuDiscInd.GetIntfId()
1916 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1917
1918 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301919 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301920 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301921 }()
1922
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301923 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1924
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301925 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1926 if !dh.cfg.ForceOnuDiscIndProcessing {
1927 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1928 if error != nil {
1929 return error
1930 }
1931 if tpInstExists {
1932 // ignore the discovery if tpinstance is present.
1933 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1934 return nil
1935 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001936 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001937 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1938
1939 // if the ONU existed, handle the LOS Alarm
1940 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001941 if inProcess.(bool) {
1942 // if we're currently processing the ONU on a different thread, do nothing
1943 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1944 return nil
1945 }
1946 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1947 // then continue processing it
1948 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1949
1950 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001951 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301952 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001953 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001954
1955 // check the ONU is already know to the OLT
1956 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301957 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001958 ParentId: dh.device.Id,
1959 SerialNumber: sn,
1960 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001961
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301962 if error != nil {
1963 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1964 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001965 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 -08001966 switch e.Code() {
1967 case codes.Internal:
1968 // this probably means NOT FOUND, so just create a new device
1969 onuDevice = nil
1970 case codes.DeadlineExceeded:
1971 // if the call times out, cleanup and exit
1972 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301973 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1974 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001975 }
1976 }
1977 }
1978
1979 if onuDevice == nil {
1980 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001982 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001983 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301984 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001986
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301987 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001988 // if we can't create an ID in resource manager,
1989 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001990 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301991
1992 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001993 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301994 "serial-number": sn}, error)
1995 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001996 }
1997
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301998 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001999 ParentId: dh.device.Id,
2000 ParentPortNo: parentPortNo,
2001 ChannelId: channelID,
2002 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
2003 SerialNumber: sn,
2004 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302005 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08002006 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00002007 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 +05302008
2009 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002010 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302011 "serial-number": sn}, error)
2012 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002013 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302014 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 +05302015 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2016 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2017 "onu-id": onuID,
2018 "device-id": dh.device.Id,
2019 "serial-number": sn}, error)
2020 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002021 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002022 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302023 log.Fields{"onuDevice": onuDevice,
2024 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002025 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302026 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002027 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002028
khenaidoo106c61a2021-08-11 18:05:46 -04002029 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2030 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302031 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002032 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302033 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302034 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2035 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002036 }
2037
Matteo Scandolo945e4012019-12-12 14:16:11 -08002038 // we can now use the existing ONU Id
2039 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302040 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002041 //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 +00002042 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002043 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302044 "intfId": onuDiscInd.GetIntfId(),
2045 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002046 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002047
khenaidoo106c61a2021-08-11 18:05:46 -04002048 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302049 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302051 log.Fields{"onu": onuDev,
2052 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002053
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302054 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002055 DeviceId: onuDevice.Id,
2056 ParentDeviceId: dh.device.Id,
2057 OperStatus: common.OperStatus_DISCOVERED,
2058 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302059 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302060 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002061 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302062 "serial-number": sn}, error)
2063 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002064 }
khenaidoo106c61a2021-08-11 18:05:46 -04002065
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302067 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302068 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002069 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302070 "serial-number": sn}, error)
2071 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002072 }
2073 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002074}
2075
Mahir Gunyelb0046752021-02-26 13:51:05 -08002076func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002077 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002078 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002079 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002080 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002081 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302082 log.Fields{"onuId": onuInd.OnuId,
2083 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302084 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002085 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002086 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 errFields := log.Fields{"device-id": dh.device.Id}
2088
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302089 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302090 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002091 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002092 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002093 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002094 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302095 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002096 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002097 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002098 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002099 errFields["onu-id"] = onuInd.OnuId
2100 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002101 }
khenaidoodc2116e2021-10-19 17:33:19 -04002102 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002103 ParentId: dh.device.Id,
2104 SerialNumber: serialNumber,
2105 OnuId: onuInd.OnuId,
2106 ParentPortNo: ponPort,
2107 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002108 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002109
David K. Bainbridge794735f2020-02-11 21:01:37 -08002110 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002111 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002112 }
2113
David K. Bainbridge794735f2020-02-11 21:01:37 -08002114 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002116 "previousIntfId": onuDevice.ParentPortNo,
2117 "currentIntfId": ponPort})
2118 }
2119
2120 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002121 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302122 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2123 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302124 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002125 }
2126 if !foundInCache {
2127 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002128 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 -08002129 }
kesavand7cf3a052020-08-28 12:49:18 +05302130 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002131 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002132 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302133 }
2134 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002135 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002136 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002137 }
2138 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002139}
2140
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002142 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 -07002143 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2144 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2145 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2146 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002147 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002148 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2149 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002151 onuInd.OperState = "down"
2152 }
2153 }
2154
David K. Bainbridge794735f2020-02-11 21:01:37 -08002155 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002156 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002157 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 -04002158
khenaidoodc2116e2021-10-19 17:33:19 -04002159 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002160 DeviceId: onuDevice.Id,
2161 OnuIndication: onuInd,
2162 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002163 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302164 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002165 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002166 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002167 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002168 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002169 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002170 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002171 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002172 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002173 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002174}
2175
cuilin20187b2a8c32019-03-26 19:52:28 -07002176func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2177 if serialNum != nil {
2178 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002179 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002180 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002181}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002182func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2183 decodedStr, err := hex.DecodeString(serialNum[4:])
2184 if err != nil {
2185 return nil, err
2186 }
2187 return &oop.SerialNumber{
2188 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002189 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002190 }, nil
2191}
cuilin20187b2a8c32019-03-26 19:52:28 -07002192
2193func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002194 if len(vendorSpecific) > 3 {
2195 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2196 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2197 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2198 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2199 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2200 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2201 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2202 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2203 return tmp
2204 }
2205 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002206}
2207
Mahir Gunyela2e68702022-12-07 00:00:42 -08002208// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002209func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302210 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002211}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002212
Mahir Gunyela2e68702022-12-07 00:00:42 -08002213// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002214func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2215 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302216 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002217 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302218 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002219
khenaidoodc2116e2021-10-19 17:33:19 -04002220 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002221 ParentId: dh.device.Id,
2222 OnuId: onuID,
2223 ParentPortNo: parentPort,
2224 })
2225
Girish Gowdru0c588b22019-04-23 23:24:56 -04002226 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002227 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002228 "intf-id": parentPort,
2229 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002230 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002231 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 -08002232 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302233}
2234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002235// SendPacketInToCore sends packet-in to core
2236// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2237// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002238func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002239 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002241 "port": logicalPort,
2242 "packet": hex.EncodeToString(packetPayload),
2243 "device-id": dh.device.Id,
2244 })
2245 }
khenaidoo106c61a2021-08-11 18:05:46 -04002246
khenaidoodc2116e2021-10-19 17:33:19 -04002247 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002248 DeviceId: dh.device.Id,
2249 Port: logicalPort,
2250 Packet: packetPayload,
2251 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302252 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002253 "source": "adapter",
2254 "destination": "core",
2255 "device-id": dh.device.Id,
2256 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002257 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002258 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002259 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002260 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002261 "packet": hex.EncodeToString(packetPayload),
2262 "device-id": dh.device.Id,
2263 })
2264 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002265 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002266}
2267
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002268// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002269func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002270 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002271
2272 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2273 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002275 }
2276
Kent Hagermane6ff1012020-07-14 15:07:53 -04002277 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002278 metrics := dh.metrics.GetSubscriberMetrics()
2279 for _, m := range pmConfigs.Metrics {
2280 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002281 }
2282 }
2283}
2284
khenaidoodc2116e2021-10-19 17:33:19 -04002285func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002286 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002287 var errorsList []error
2288
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002289 if dh.getDeviceDeletionInProgressFlag() {
2290 // The device itself is going to be reset as part of deletion. So nothing to be done.
2291 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2292 return nil
2293 }
2294
Girish Gowdru0c588b22019-04-23 23:24:56 -04002295 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002296 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302297 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002298
Neha Sharma96b7bf22020-06-15 10:37:32 +00002299 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302300 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002301 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302302 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002303 if flow_utils.HasGroup(flow) {
2304 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2305 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002306 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2307 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2308 } else {
2309 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2310 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002311 }
Girish Gowdracefae192020-03-19 18:14:10 -07002312 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002313 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302314 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002315 logger.Warnw(ctx, "flow-to-remove-not-found",
2316 log.Fields{
2317 "ponIf": intfID,
2318 "flowToRemove": flow,
2319 "error": err,
2320 })
2321 } else {
2322 errorsList = append(errorsList, err)
2323 }
Girish Gowdracefae192020-03-19 18:14:10 -07002324 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002325 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302326
2327 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302328 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302330 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002331 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302332 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002333 if flow_utils.HasGroup(flow) {
2334 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2335 } else {
yasin saplid0566272021-12-21 09:10:30 +00002336 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002337 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2338 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2339 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2340 } else {
yasin saplid0566272021-12-21 09:10:30 +00002341 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002342 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002343 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002344 if err != nil {
2345 errorsList = append(errorsList, err)
2346 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302347 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002348 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002349
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002350 return errorsList
2351}
2352
2353func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2354 var err error
2355 var errorsList []error
2356
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002357 if dh.getDeviceDeletionInProgressFlag() {
2358 // The device itself is going to be reset as part of deletion. So nothing to be done.
2359 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2360 return nil
2361 }
2362
Girish Gowdracefae192020-03-19 18:14:10 -07002363 // 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 +00002364 if groups != nil {
2365 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002366 // err = dh.groupMgr.AddGroup(ctx, group)
2367 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002368 if err != nil {
2369 errorsList = append(errorsList, err)
2370 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002371 }
2372 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002373 // err = dh.groupMgr.ModifyGroup(ctx, group)
2374 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002375 if err != nil {
2376 errorsList = append(errorsList, err)
2377 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002378 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002379 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002380 // err = dh.groupMgr.DeleteGroup(ctx, group)
2381 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002382 if err != nil {
2383 errorsList = append(errorsList, err)
2384 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002385 }
2386 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002387
2388 return errorsList
2389}
2390
Mahir Gunyela2e68702022-12-07 00:00:42 -08002391// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002392func (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 -07002393 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002394
2395 if dh.getDeviceDeletionInProgressFlag() {
2396 // The device itself is going to be reset as part of deletion. So nothing to be done.
2397 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2398 return nil
2399 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302400 if dh.transitionMap.currentDeviceState != deviceStateUp {
2401 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2402 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2403 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002404 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2405 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2406 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002407 if len(errorsList) > 0 {
2408 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2409 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002410 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002411 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302412}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002413
Mahir Gunyela2e68702022-12-07 00:00:42 -08002414// DisableDevice disables the given device
2415// It marks the following for the given device:
2416// Device-Handler Admin-State : down
2417// Device Port-State: UNKNOWN
2418// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002420 /* On device disable ,admin state update has to be done prior sending request to agent since
2421 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002422 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002423 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002424 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002425 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002426 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002427 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002428 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002430 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002431 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302432
2433 dh.discOnus = sync.Map{}
2434 dh.onus = sync.Map{}
2435
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002436 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302437 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002438 if dh.isCollectorActive {
2439 dh.stopCollector <- true
2440 }
2441 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302442
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002444 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302445 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302446 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002447
kdarapu1afeceb2020-02-12 01:38:09 -05002448 // 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 -04002449 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002450 DeviceId: cloned.Id,
2451 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2452 OperStatus: voltha.OperStatus_UNKNOWN,
2453 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002454 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002455 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002456 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002457 return nil
2458}
2459
Neha Sharma96b7bf22020-06-15 10:37:32 +00002460func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002461 // Update onu state as unreachable in onu adapter
2462 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302463 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002464
Akash Kankanala041a2122024-10-16 15:49:22 +05302465 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002466 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002467 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002468 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 -04002469 }
2470 if onuDevices != nil {
2471 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002472 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002473 DeviceId: onuDevice.Id,
2474 OnuIndication: &onuInd,
2475 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002476 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002477 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002478 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002479 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002480 }
2481 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002482}
2483
Mahir Gunyela2e68702022-12-07 00:00:42 -08002484// ReenableDevice re-enables the olt device after disable
2485// It marks the following for the given device:
2486// Device-Handler Admin-State : up
2487// Device Port-State: ACTIVE
2488// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002489func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302490 if dh.Client != nil {
2491 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2492 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2493 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2494 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302495 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302496 } else {
2497 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 +05302498 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002499 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002500
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002501 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002502 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002503 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002504 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002505 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2506 } else {
2507 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2508 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2509 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002510 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002511 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302512 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002513 device.OperStatus = voltha.OperStatus_ACTIVE
2514 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302515 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002516 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002517 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002518 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002519
khenaidoodc2116e2021-10-19 17:33:19 -04002520 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002521 DeviceId: device.Id,
2522 OperStatus: device.OperStatus,
2523 ConnStatus: device.ConnectStatus,
2524 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302525 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002526 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002527 "connect-status": device.ConnectStatus,
2528 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002529 }
kesavand39e0aa32020-01-28 20:58:50 -05002530
Neha Sharma96b7bf22020-06-15 10:37:32 +00002531 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002532
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002533 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002534}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002535
npujarec5762e2020-01-01 14:08:48 +05302536func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002537 var uniID uint32
2538 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002539 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302540 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002541 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002542 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002543 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002544 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2545 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2546 } else {
2547 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2548 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002549 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002550 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002551 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002552 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002553 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002554 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002555 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002556 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002557 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002558 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002559 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002560 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002561 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002562 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002563 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002564 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302565 }
yasin saplibddc2d72022-02-08 13:10:17 +00002566 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2567 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002568 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002569 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002571 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002572 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002573 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 -03002574 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002575 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002576 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002577 if len(errs) > 0 {
2578 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2579 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2580 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002581 return nil
2582}
2583
Devmalya Paul495b94a2019-08-27 19:42:00 -04002584// 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 +05302585func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002586 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002587 /* Clear the KV store data associated with the all the UNI ports
2588 This clears up flow data and also resource map data for various
2589 other pon resources like alloc_id and gemport_id
2590 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002591
Abhay Kumarb87ac882025-10-30 09:55:07 +00002592 if dh.getDeviceDeletionInProgressFlag() {
2593 logger.Errorw(ctx, "cannot complete operation as device deletion is in progress", log.Fields{"device-id": dh.device.Id})
2594 return olterrors.NewErrAdapter(fmt.Errorf("cannot complete operation as device deletion is in progress").Error(), log.Fields{"device-id": dh.device.Id}, nil)
2595 }
2596
Girish Gowdra950326e2021-11-05 12:43:24 -07002597 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002598 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002599
Himani Chawla49a5d562020-11-25 11:53:44 +05302600 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002601 // Stop the Stats collector
2602 if dh.isCollectorActive {
2603 dh.stopCollector <- true
2604 }
2605 // stop the heartbeat check routine
2606 if dh.isHeartbeatCheckActive {
2607 dh.stopHeartbeatCheck <- true
2608 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302609 // Stop the read indication only if it the routine is active
2610 if dh.isReadIndicationRoutineActive {
2611 dh.stopIndications <- true
2612 }
2613 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302614
2615 err := dh.cleanupDeviceResources(ctx)
2616 if err != nil {
2617 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2618 } else {
2619 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2620 }
2621
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002622 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302623 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002624 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302625 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002626 go func() {
2627 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302628 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2629 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002630 }
2631 }()
2632 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002633 }
2634 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002635 // There is no need to update the core about operation status and connection status of the OLT.
2636 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2637 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2638 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002639
khenaidoo7eb2d672021-10-22 19:08:50 -04002640 // Stop the adapter grpc clients for that parent device
2641 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002642 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002643}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002644
2645// StopAllFlowRoutines stops all flow routines
2646func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2647 var wg sync.WaitGroup
2648 wg.Add(1) // for the mcast routine below to finish
2649 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2650 for _, flMgr := range dh.flowMgr {
2651 if flMgr != nil {
2652 wg.Add(1) // for the flow handler routine below to finish
2653 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2654 }
2655 }
2656 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2657 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2658 } else {
2659 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2660 }
2661}
2662
Gustavo Silva41af9122022-10-11 11:05:13 -03002663func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2664 var errs []error
Abhay Kumarb87ac882025-10-30 09:55:07 +00002665 if dh.resourceMgr != nil && dh.totalPonPorts > 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302666 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002667 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002668 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002669 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002670 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002671 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2672 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302673 }
2674 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002675 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2676 errs = append(errs, err)
2677 }
2678 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2679 errs = append(errs, err)
2680 }
2681 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2682 errs = append(errs, err)
2683 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002684 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002685 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002686 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002687 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002688 }
2689 // Clean up NNI manager's data
2690 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2691 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002692 }
A R Karthick1f85b802019-10-11 05:06:05 +00002693
Abhay Kumarb87ac882025-10-30 09:55:07 +00002694 logger.Debugw(ctx, "lockDevice for KVStore close client", log.Fields{"deviceID": dh.device.Id})
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002695 dh.CloseKVClient(ctx)
2696
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002697 // Take one final sweep at cleaning up KV store for the OLT device
2698 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002699 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2700 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002701 }
2702
Devmalya Paul495b94a2019-08-27 19:42:00 -04002703 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302704 dh.onus.Range(func(key interface{}, value interface{}) bool {
2705 dh.onus.Delete(key)
2706 return true
2707 })
2708
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002709 /*Delete discovered ONU map for the device*/
2710 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2711 dh.discOnus.Delete(key)
2712 return true
2713 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002714 if len(errs) > 0 {
2715 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2716 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2717 }
2718 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002719}
2720
Mahir Gunyela2e68702022-12-07 00:00:42 -08002721// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002722func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302723 if dh.Client != nil {
2724 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2725 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2726 }
2727 } else {
2728 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 -04002729 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302730
Neha Sharma96b7bf22020-06-15 10:37:32 +00002731 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002732 return nil
2733}
2734
David K. Bainbridge794735f2020-02-11 21:01:37 -08002735func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002736 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002737 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002738 "packet-indication": *packetIn,
2739 "device-id": dh.device.Id,
2740 "packet": hex.EncodeToString(packetIn.Pkt),
2741 })
2742 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002743 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2744 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2745 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002746 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002747 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002748 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002749 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002750 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002751 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002752 "logical-port-num": logicalPortNum,
2753 "device-id": dh.device.Id,
2754 "packet": hex.EncodeToString(packetIn.Pkt),
2755 })
2756 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002757
khenaidoodc2116e2021-10-19 17:33:19 -04002758 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002759 DeviceId: dh.device.Id,
2760 Port: logicalPortNum,
2761 Packet: packetIn.Pkt,
2762 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302763 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002764 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302765 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002766 "device-id": dh.device.Id,
2767 "packet": hex.EncodeToString(packetIn.Pkt),
2768 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002769 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770
Matteo Scandolo92186242020-06-12 10:54:18 -07002771 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002772 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002773 "packet": hex.EncodeToString(packetIn.Pkt),
2774 "device-id": dh.device.Id,
2775 })
2776 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002777 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002778}
2779
Mahir Gunyela2e68702022-12-07 00:00:42 -08002780// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2781func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2782 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2783 if err != nil {
2784 return olterrors.NewErrInvalidValue(log.Fields{
2785 "egress-nni-port": egressPortNo,
2786 "device-id": dh.device.Id,
2787 }, err)
2788 }
2789 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2790
2791 if logger.V(log.DebugLevel) {
2792 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2793 "uplink-pkt": uplinkPkt,
2794 "packet": hex.EncodeToString(packet.Data),
2795 "device-id": dh.device.Id,
2796 })
2797 }
2798
2799 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2800 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2801 "packet": hex.EncodeToString(packet.Data),
2802 "device-id": dh.device.Id,
2803 }, err)
2804 }
2805 return nil
2806}
2807
2808// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2809func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2810 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2811 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2812 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2813 // Do not packet-out lldp packets on uni port.
2814 // ONOS has no clue about uni/nni ports, it just packets out on all
2815 // available ports on the Logical Switch. It should not be interested
2816 // in the UNI links.
2817 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2818 "device-id": dh.device.Id,
2819 })
2820 return nil
2821 }
2822 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2823 if innerEthType == 0x8100 {
2824 // q-in-q 802.1ad or 802.1q double tagged packet.
2825 // slice out the outer tag.
2826 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2827 if logger.V(log.DebugLevel) {
2828 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2829 "packet-data": hex.EncodeToString(packet.Data),
2830 "device-id": dh.device.Id,
2831 })
2832 }
2833 }
2834 }
2835 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2836 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2837 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2838 var gemPortID uint32
2839 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2840 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2841 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2842 }
2843 if err != nil {
2844 // In this case the openolt agent will receive the gemPortID as 0.
2845 // The agent tries to retrieve the gemPortID in this case.
2846 // This may not always succeed at the agent and packetOut may fail.
2847 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2848 "intf-id": intfID,
2849 "onu-id": onuID,
2850 "uni-id": uniID,
2851 "packet": hex.EncodeToString(packet.Data),
2852 "device-id": dh.device.Id,
2853 "error": err,
2854 })
2855 }
2856
2857 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2858 if logger.V(log.DebugLevel) {
2859 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2860 "egress-port-no": egressPortNo,
2861 "intf-id": intfID,
2862 "onu-id": onuID,
2863 "uni-id": uniID,
2864 "gem-port-id": gemPortID,
2865 "packet": hex.EncodeToString(packet.Data),
2866 "device-id": dh.device.Id,
2867 })
2868 }
2869
2870 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2871 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2872 "source": "adapter",
2873 "destination": "onu",
2874 "egress-port-number": egressPortNo,
2875 "intf-id": intfID,
2876 "oni-id": onuID,
2877 "uni-id": uniID,
2878 "gem-port-id": gemPortID,
2879 "packet": hex.EncodeToString(packet.Data),
2880 "device-id": dh.device.Id,
2881 }, err)
2882 }
2883 return nil
2884}
2885
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002886// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002887func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002888 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002889 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002890 "device-id": dh.device.Id,
2891 "egress-port-no": egressPortNo,
2892 "pkt-length": len(packet.Data),
2893 "packet": hex.EncodeToString(packet.Data),
2894 })
2895 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002896
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002897 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002898 var err error
mgouda86543582025-10-29 20:58:16 +05302899 switch egressPortType {
2900 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002901 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302902 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002903 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302904 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002905 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302906 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002907 "egressPortType": egressPortType,
2908 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302909 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002910 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002911 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002912 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002913}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002914
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002915func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2916 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002917}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302918
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002919func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002920 defer func() {
2921 dh.lockDevice.Lock()
2922 dh.isHeartbeatCheckActive = false
2923 dh.lockDevice.Unlock()
2924 }()
2925
2926 dh.lockDevice.Lock()
2927 dh.isHeartbeatCheckActive = true
2928 dh.lockDevice.Unlock()
2929
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302930 // start the heartbeat check towards the OLT.
2931 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302932 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302933
2934 for {
2935 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2936 select {
2937 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002938 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002939 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002940 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302941 if timerCheck == nil {
2942 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002943 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302944 }
2945 } else {
2946 if timerCheck != nil {
2947 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002948 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302949 }
2950 timerCheck = nil
2951 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302952 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2953 if dh.heartbeatSignature == 0 {
2954 // First time the signature will be 0, update the signture to DB when not found.
2955 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2956 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2957 }
2958 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2959
2960 dh.lockDevice.RLock()
2961 // Stop the read indication only if it the routine is active
2962 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2963 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2964 // on next execution of the readIndication routine.
2965 if !dh.isReadIndicationRoutineActive {
2966 // Start reading indications
2967 go func() {
2968 if err = dh.readIndications(ctx); err != nil {
2969 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2970 }
2971 }()
2972 }
2973 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302974 } else {
2975 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2976 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2977 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2978 go dh.updateStateRebooted(ctx)
2979 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302980 }
2981 cancel()
2982 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002983 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302984 return
2985 }
2986 }
2987}
2988
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002989func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002990 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002991 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002992 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2993 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2994 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2995 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2996 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002997 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002998 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2999 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003000 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303001
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303002 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07003003 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003004 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04003005 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04003006 DeviceId: dh.device.Id,
3007 OperStatus: voltha.OperStatus_UNKNOWN,
3008 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
3009 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003010 _ = 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 -04003011 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303012 /*
3013 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
3014 DeviceId: dh.device.Id,
3015 PortTypeFilter: 0,
3016 OperStatus: voltha.OperStatus_UNKNOWN,
3017 }); err != nil {
3018 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3019 }
3020 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003021
Akash Kankanala041a2122024-10-16 15:49:22 +05303022 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003023 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003024 cloned := proto.Clone(device).(*voltha.Device)
3025 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3026 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3027 dh.device = cloned // update local copy of the device
3028 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003029
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003030 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003031 // Stop the Stats collector
3032 if dh.isCollectorActive {
3033 dh.stopCollector <- true
3034 }
3035 // stop the heartbeat check routine
3036 if dh.isHeartbeatCheckActive {
3037 dh.stopHeartbeatCheck <- true
3038 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003039 // Stop the read indication only if it the routine is active
3040 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3041 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3042 // on next execution of the readIndication routine.
3043 if dh.isReadIndicationRoutineActive {
3044 dh.stopIndications <- true
3045 }
3046 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003047 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303048 }
3049}
kesavand39e0aa32020-01-28 20:58:50 -05003050
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303051func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3052 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3053 if err != nil || device == nil {
3054 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3055 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3056 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3057 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3058 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3059 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3060 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3061 return
3062 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303063 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003064 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303065
3066 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3067 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303068 // First, stop the read indication and heartbeat check routines to prevent any delay
3069 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303070 dh.lockDevice.RLock()
3071 // Stop the read indication only if it the routine is active
3072 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3073 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3074 // on next execution of the readIndication routine.
3075 if dh.isReadIndicationRoutineActive {
3076 dh.stopIndications <- true
3077 }
3078 dh.lockDevice.RUnlock()
3079
bseenivad1c984b2025-01-09 12:54:44 +05303080 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3081 DeviceId: dh.device.Id,
3082 OperStatus: voltha.OperStatus_REBOOTED,
3083 ConnStatus: voltha.ConnectStatus_REACHABLE,
3084 }); err != nil {
3085 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3086 }
3087
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303088 //raise olt communication failure event
3089 raisedTs := time.Now().Unix()
3090 cloned := proto.Clone(device).(*voltha.Device)
3091 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3092 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3093 dh.device = cloned // update local copy of the device
3094 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3095
Gustavo Silva41af9122022-10-11 11:05:13 -03003096 if err := dh.cleanupDeviceResources(ctx); err != nil {
3097 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3098 } else {
3099 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3100 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003101
3102 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303103 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003104 if dh.isCollectorActive {
3105 dh.stopCollector <- true
3106 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303107 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003108 if dh.isHeartbeatCheckActive {
3109 dh.stopHeartbeatCheck <- true
3110 }
3111 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303112
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003113 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303114
Akash Kankanala041a2122024-10-16 15:49:22 +05303115 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303116 dh.adapterPreviouslyConnected = false
3117 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303118 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3119 if err != nil || childDevices == nil {
3120 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3121 continue
3122 }
3123 if len(childDevices.Items) == 0 {
3124 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3125 break
3126 } else {
3127 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3128 time.Sleep(5 * time.Second)
3129 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303130 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303131 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003132 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303133 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3134 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303135}
3136
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303137// EnableOnuSerialNumber to enable onu serial number
3138func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3139 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3140 onuSerialNumber := device.SerialNumber
3141
3142 // fetch interfaceid from PortNo
3143 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3144
3145 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3146 if err != nil {
3147 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3148 log.Fields{
3149 "devicer-id": dh.device.Id,
3150 "serial-number": onuSerialNumber}, err).Log()
3151 }
3152
3153 onuIntf := &oop.InterfaceOnuSerialNumber{
3154 IntfId: ponID,
3155 OnuSerialNumber: sn,
3156 }
3157 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3158
3159 if err != nil {
3160 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3161 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3162 "device-id": dh.device.Id,
3163 "onu-serial-number": onuSerialNumber}, err)
3164 }
3165 return nil
3166}
3167
3168// DisableOnuSerialNumber to disable onu serial number
3169func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3170 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3171 onuSerialNumber := device.SerialNumber
3172 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3173 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3174 if err != nil {
3175 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3176 log.Fields{
3177 "devicer-id": dh.device.Id,
3178 "serial-number": onuSerialNumber}, err).Log()
3179 }
3180
3181 onuIntf := &oop.InterfaceOnuSerialNumber{
3182 OnuSerialNumber: sn,
3183 IntfId: ponID,
3184 }
3185 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3186
3187 if err != nil {
3188 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3189 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3190 "device-id": dh.device.Id,
3191 "onu-serial-number": onuSerialNumber}, err)
3192 }
3193 return nil
3194}
3195
3196// EnableOnu to enable onu
3197func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3198 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3199 onuSerialNumber := device.SerialNumber
3200 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3201 if InCacheOnuDev == nil {
3202 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3203 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3204 "device-id": dh.device.Id,
3205 "onu-serial-number": onuSerialNumber}, nil)
3206 }
3207 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})
3208
3209 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3210 if err != nil {
3211 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3212 log.Fields{
3213 "device-id": dh.device.Id,
3214 "serial-number": onuSerialNumber}, err).Log()
3215 }
3216
3217 onuIntf := &oop.InterfaceOnuSerialNumber{
3218 OnuSerialNumber: sn,
3219 IntfId: InCacheOnuDev.intfID,
3220 }
3221 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3222 OnuId: InCacheOnuDev.onuID,
3223 IntfIdSerialNum: onuIntf,
3224 }
3225 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3226
3227 if err != nil {
3228 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3229 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3230 "olt-device-id": dh.device.Id,
3231 "onu-serial-number": onuSerialNumber}, err)
3232 }
3233 return nil
3234}
3235
3236// DisableOnu to disable onu
3237func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3238 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3239 onuSerialNumber := device.SerialNumber
3240 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3241 if InCacheOnuDev == nil {
3242 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3243 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3244 "device-id": dh.device.Id,
3245 "onu-serial-number": onuSerialNumber}, nil)
3246 }
3247 logger.Debugw(ctx, "successfully-received-child-device-from-cache", log.Fields{"child-device-intfid": InCacheOnuDev.intfID, "child-device-sn": InCacheOnuDev.serialNumber, "child-onuid": InCacheOnuDev.onuID})
3248
3249 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3250 if err != nil {
3251 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3252 log.Fields{
3253 "device-id": dh.device.Id,
3254 "serial-number": onuSerialNumber}, err).Log()
3255 }
3256
3257 onuIntf := &oop.InterfaceOnuSerialNumber{
3258 OnuSerialNumber: sn,
3259 IntfId: InCacheOnuDev.intfID,
3260 }
3261 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3262 OnuId: InCacheOnuDev.onuID,
3263 IntfIdSerialNum: onuIntf,
3264 }
3265 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3266
3267 if err != nil {
3268 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3269 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3270 "olt-device-id": dh.device.Id,
3271 "onu-serial-number": onuSerialNumber}, err)
3272 }
3273 return nil
3274}
3275
kesavand39e0aa32020-01-28 20:58:50 -05003276// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003277func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3278 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3279 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003280}
3281
3282// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003283func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3284 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3285 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003286}
3287
Mahir Gunyela2e68702022-12-07 00:00:42 -08003288// 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 +00003289func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3290 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003291 if port.GetType() == voltha.Port_ETHERNET_NNI {
3292 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003293 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303294 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303295 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003296 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003297 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003298 }
3299 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003300 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003301 ponIntf := &oop.Interface{IntfId: ponID}
3302 var operStatus voltha.OperStatus_Types
3303 if enablePort {
3304 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303305 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003306
3307 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303308 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003309 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003310 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003311 }
3312 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003313 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003314 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003315 } else {
3316 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303317 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003318 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303319 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003320 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003321 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003322 }
3323 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003324 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003325 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003326 }
khenaidoodc2116e2021-10-19 17:33:19 -04003327 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003328 DeviceId: dh.device.Id,
3329 PortType: voltha.Port_PON_OLT,
3330 PortNo: port.PortNo,
3331 OperStatus: operStatus,
3332 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303333 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303334 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003335 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003336 }
3337 return nil
3338}
3339
Mahir Gunyela2e68702022-12-07 00:00:42 -08003340// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003341func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003342 // Disable the port and update the oper_port_status to core
3343 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003344 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003345 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003346 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303347 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303348 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003349 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003350 }
3351 }
3352 }
3353 return nil
3354}
3355
Mahir Gunyela2e68702022-12-07 00:00:42 -08003356// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003357func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3358 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3359 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003360 if port.Type == voltha.Port_ETHERNET_NNI {
3361 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003362 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003363 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003364 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003365 }
3366 }
3367 if port.Type == voltha.Port_PON_OLT {
3368 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003369 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003370 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003371 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003372 }
3373 }
3374 }
3375}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003376
3377// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003378func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003379 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003380 if dh.getDeviceDeletionInProgressFlag() {
3381 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3382 // will reboot, so everything will be reset on the pOLT too.
3383 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3384 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3385 return nil
3386 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303387
3388 if dh.transitionMap.currentDeviceState != deviceStateUp {
3389 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})
3390 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3391 }
3392
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003393 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003394 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003395
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003396 var sn *oop.SerialNumber
3397 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003398 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303399 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003400 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303401 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003402 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003403 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003404
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003405 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303406 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003407 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003408 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3409 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3410 "device-id": dh.device.Id,
3411 "intf-id": intfID,
3412 "onuID": onuID,
3413 "err": err})
3414 } else {
3415 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003416 // Delete flows from device before schedulers and queue
3417 // Clear flowids for gem cache.
3418 removedFlows := []uint64{}
3419 for _, gem := range onuGem.GemPorts {
3420 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3421 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303422 // multiple gem port can have the same flow id
3423 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003424 var alreadyRemoved bool
3425 for _, removedFlowID := range removedFlows {
3426 if removedFlowID == flowID {
3427 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3428 alreadyRemoved = true
3429 break
3430 }
3431 }
3432 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003433 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003434 removedFlows = appendUnique64bit(removedFlows, flowID)
3435 }
3436 }
3437 }
3438 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3439 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003440 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3441 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3442 "device-id": dh.device.Id,
3443 "onu-device": onu,
3444 "err": err})
3445 }
yasin saplibddc2d72022-02-08 13:10:17 +00003446 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003447 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3448 "intf-id": intfID,
3449 "onu-device": onu,
3450 "onu-gem": onuGem,
3451 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303452 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003453 }
3454 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003455 }
yasin saplibddc2d72022-02-08 13:10:17 +00003456 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003457 dh.onus.Delete(onuKey)
3458 dh.discOnus.Delete(onuSn)
3459
3460 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003461 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303462 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303463 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003464 "onu-id": onuID}, err).Log()
3465 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003466
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003467 return nil
3468}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003469func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3470 flow := &oop.Flow{FlowId: flowID}
3471 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3472 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3473 "device-id": dh.device.Id})
3474 } else {
3475 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3476 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3477 "device-id": dh.device.Id,
3478 "err": err})
3479 }
3480 }
3481}
Girish Gowdracefae192020-03-19 18:14:10 -07003482
3483func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003484 for _, field := range flow_utils.GetOfbFields(flow) {
3485 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003486 return field.GetPort()
3487 }
3488 }
3489 return InvalidPort
3490}
3491
3492func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003493 for _, action := range flow_utils.GetActions(flow) {
3494 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003495 if out := action.GetOutput(); out != nil {
3496 return out.GetPort()
3497 }
3498 }
3499 }
3500 return InvalidPort
3501}
3502
Girish Gowdracefae192020-03-19 18:14:10 -07003503func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3504 inPort := getInPortFromFlow(flow)
3505 outPort := getOutPortFromFlow(flow)
3506
3507 if inPort == InvalidPort || outPort == InvalidPort {
3508 return inPort, outPort
3509 }
3510
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003511 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003512 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003513 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 } else {
3519 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003520 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003521 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003522 return inPort, uniPort
3523 }
3524 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003525 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003526 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003527 return uniPort, outPort
3528 }
3529 }
3530 }
3531
3532 return InvalidPort, InvalidPort
3533}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003534
3535func extractOmciTransactionID(omciPkt []byte) uint16 {
3536 if len(omciPkt) > 3 {
3537 d := omciPkt[0:2]
3538 transid := binary.BigEndian.Uint16(d)
3539 return transid
3540 }
3541 return 0
3542}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003543
3544// StoreOnuDevice stores the onu parameters to the local cache.
3545func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3546 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3547 dh.onus.Store(onuKey, onuDevice)
3548}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003549
khenaidoodc2116e2021-10-19 17:33:19 -04003550func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003551 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003552 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003553 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003554 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003555 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003556 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003557 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003558 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3559 return nil, err
3560 }
3561 ID = device.ProxyAddress.GetOnuId()
3562 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3563 valueparam.Onu = &Onu
3564 valueparam.Value = value
3565
3566 // This API is unsupported until agent patch is added
3567 resp.Unsupported = uint32(value)
3568 _ = ctx
3569
3570 // Uncomment this code once agent changes are complete and tests
3571 /*
3572 resp, err = dh.Client.GetValue(ctx, valueparam)
3573 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003574 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003575 return nil, err
3576 }
3577 */
3578
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003579 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 -08003580 return resp, nil
3581}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003582
Akash Kankanala041a2122024-10-16 15:49:22 +05303583func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003584 // Default to NNI
3585 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003586 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003587 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003588 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003589 }
3590 return intfID
3591}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003592
Akash Kankanala041a2122024-10-16 15:49:22 +05303593func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003594 dh.perPonOnuIndicationChannelLock.Lock()
3595 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3596 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003597 return ch.indicationChannel
3598 }
3599 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303600 // We create a buffered channel here to avoid calling function to be blocked
3601 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003602 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003603 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003604 stopChannel: make(chan struct{}),
3605 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003606 dh.perPonOnuIndicationChannel[intfID] = channels
3607 dh.perPonOnuIndicationChannelLock.Unlock()
3608 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003609 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003610}
3611
Mahir Gunyelb0046752021-02-26 13:51:05 -08003612func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3613 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3614 dh.perPonOnuIndicationChannelLock.Lock()
3615 defer dh.perPonOnuIndicationChannelLock.Unlock()
3616 for _, v := range dh.perPonOnuIndicationChannel {
3617 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003618 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003619 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003620}
3621
Mahir Gunyelb0046752021-02-26 13:51:05 -08003622func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3623 ind := onuIndicationMsg{
3624 ctx: ctx,
3625 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003626 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003627 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003628 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303629 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003630}
3631
Mahir Gunyelb0046752021-02-26 13:51:05 -08003632func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003633 for {
3634 select {
3635 // process one indication per onu, before proceeding to the next one
3636 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003637 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003638 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003639 "ind": indication})
3640 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003641 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003642 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003643 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3644 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003645 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003646 }
3647 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003648 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003649 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3650 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003651 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003652 }
3653 }
3654 case <-onuChannels.stopChannel:
3655 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3656 close(onuChannels.indicationChannel)
3657 return
3658 }
3659 }
3660}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003661
3662// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3663// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003664func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003665 if dh.getDeviceDeletionInProgressFlag() {
3666 // The device itself is going to be reset as part of deletion. So nothing to be done.
3667 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3668 return nil
3669 }
3670
Girish Gowdra491a9c62021-01-06 16:43:07 -08003671 // Step1 : Fill McastFlowOrGroupControlBlock
3672 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3673 // Step3 : Wait on response channel for response
3674 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003675 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003676 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3677 errChan := make(chan error)
3678 var groupID uint32
3679 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3680 ctx: ctx,
3681 flowOrGroupAction: action,
3682 flow: flow,
3683 group: group,
3684 errChan: &errChan,
3685 }
3686 if flow != nil {
3687 groupID = flow_utils.GetGroup(flow)
3688 } else if group != nil {
3689 groupID = group.Desc.GroupId
3690 } else {
3691 return errors.New("flow-and-group-both-nil")
3692 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003693 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3694 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3695 // Derive the appropriate go routine to handle the request by a simple module operation.
3696 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3697 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3698 // Wait for handler to return error value
3699 err := <-errChan
3700 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3701 return err
3702 }
3703 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3704 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003705}
3706
3707// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003708func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003709 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003710 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003711 // block on the channel to receive an incoming mcast flow/group
3712 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003713 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3714 if mcastFlowOrGroupCb.flow != nil {
3715 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3716 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3717 log.Fields{"device-id": dh.device.Id,
3718 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003719 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3720 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3721 for _, flMgr := range dh.flowMgr {
3722 if flMgr != nil {
3723 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3724 break
3725 }
3726 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003727 // Pass the return value over the return channel
3728 *mcastFlowOrGroupCb.errChan <- err
3729 } else { // flow remove
3730 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3731 log.Fields{"device-id": dh.device.Id,
3732 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003733 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3734 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3735 for _, flMgr := range dh.flowMgr {
3736 if flMgr != nil {
3737 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3738 break
3739 }
3740 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003741 // Pass the return value over the return channel
3742 *mcastFlowOrGroupCb.errChan <- err
3743 }
3744 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303745 switch mcastFlowOrGroupCb.flowOrGroupAction {
3746 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003747 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3748 log.Fields{"device-id": dh.device.Id,
3749 "groupToAdd": mcastFlowOrGroupCb.group})
3750 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3751 // Pass the return value over the return channel
3752 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303753 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003754 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3755 log.Fields{"device-id": dh.device.Id,
3756 "groupToModify": mcastFlowOrGroupCb.group})
3757 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3758 // Pass the return value over the return channel
3759 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303760 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003761 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3762 log.Fields{"device-id": dh.device.Id,
3763 "groupToRemove": mcastFlowOrGroupCb.group})
3764 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3765 // Pass the return value over the return channel
3766 *mcastFlowOrGroupCb.errChan <- err
3767 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003768 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003769 case <-stopHandler:
3770 dh.mcastHandlerRoutineActive[routineIndex] = false
3771 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003772 }
3773 }
3774}
kesavand62126212021-01-12 04:56:06 -05003775
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003776// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003777func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003778 for i, v := range dh.stopMcastHandlerRoutine {
3779 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003780 select {
3781 case v <- true:
3782 case <-time.After(time.Second * 5):
3783 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3784 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003785 }
3786 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003787
3788 if dh.incomingMcastFlowOrGroup != nil {
3789 for k := range dh.incomingMcastFlowOrGroup {
3790 if dh.incomingMcastFlowOrGroup[k] != nil {
3791 dh.incomingMcastFlowOrGroup[k] = nil
3792 }
3793 }
3794 dh.incomingMcastFlowOrGroup = nil
3795 }
3796
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003797 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003798 logger.Debug(ctx, "stopped all mcast handler routines")
3799}
3800
Akash Kankanala041a2122024-10-16 15:49:22 +05303801// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003802func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003803 singleValResp := extension.SingleGetValueResponse{
3804 Response: &extension.GetValueResponse{
3805 Response: &extension.GetValueResponse_PortCoutners{
3806 PortCoutners: &extension.GetOltPortCountersResponse{},
3807 },
3808 },
3809 }
3810
Akash Kankanala041a2122024-10-16 15:49:22 +05303811 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003812 return &extension.SingleGetValueResponse{
3813 Response: &extension.GetValueResponse{
3814 Status: status,
3815 ErrReason: reason,
3816 },
3817 }
3818 }
3819
3820 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3821 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303822 // send error response
kesavand62126212021-01-12 04:56:06 -05003823 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3824 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3825 }
3826 statIndChn := make(chan bool, 1)
3827 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3828 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303829 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003830
3831 go func() {
3832 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3833 if err != nil {
3834 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3835 }
3836 }()
3837 select {
3838 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303839 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003840 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3841 case <-time.After(oltPortInfoTimeout * time.Second):
3842 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3843 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3844 case <-ctx.Done():
3845 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3846 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3847 }
mgouda86543582025-10-29 20:58:16 +05303848 switch oltPortInfo.PortType {
3849 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303850 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003851 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003852 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3853 cmnni := dh.portStats.collectNNIMetrics(intfID)
3854 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303855 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003856 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3857 }
3858 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3859 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303860 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003861 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003862 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003863 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3864 cmpon := dh.portStats.collectPONMetrics(intfID)
3865 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303866 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003867 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3868 }
3869 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3870 return &singleValResp
3871 }
3872 }
3873 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3874}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303875
Akash Kankanala041a2122024-10-16 15:49:22 +05303876//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303877func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303878 singleValResp := extension.SingleGetValueResponse{
3879 Response: &extension.GetValueResponse{
3880 Status: extension.GetValueResponse_OK,
3881 Response: &extension.GetValueResponse_OffloadedAppsStats{
3882 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3883 },
3884 },
3885 }
3886
3887 return &singleValResp
3888}
3889
Akash Kankanala041a2122024-10-16 15:49:22 +05303890//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303891func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303892 singleValResp := extension.SingleSetValueResponse{
3893 Response: &extension.SetValueResponse{
3894 Status: extension.SetValueResponse_OK,
3895 },
3896 }
3897
3898 return &singleValResp
3899}
3900
Akash Kankanala041a2122024-10-16 15:49:22 +05303901//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303902func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303903 singleValResp := extension.SingleSetValueResponse{
3904 Response: &extension.SetValueResponse{
3905 Status: extension.SetValueResponse_OK,
3906 },
3907 }
3908
3909 return &singleValResp
3910}
3911
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303912func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303913 singleValResp := extension.SingleGetValueResponse{
3914 Response: &extension.GetValueResponse{
3915 Response: &extension.GetValueResponse_OnuPonCounters{
3916 OnuPonCounters: &extension.GetOnuCountersResponse{},
3917 },
3918 },
3919 }
3920
Akash Kankanala041a2122024-10-16 15:49:22 +05303921 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303922 return &extension.SingleGetValueResponse{
3923 Response: &extension.GetValueResponse{
3924 Status: status,
3925 ErrReason: reason,
3926 },
3927 }
3928 }
3929 intfID := onuPonInfo.IntfId
3930 onuID := onuPonInfo.OnuId
3931 onuKey := dh.formOnuKey(intfID, onuID)
3932
3933 if _, ok := dh.onus.Load(onuKey); !ok {
3934 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3935 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3936 }
3937 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3938 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3939 if cmnni == nil {
3940 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3941 }
3942 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3943 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303944}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003945
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303946func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3947 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3948 if err != nil {
3949 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3950 return nil, err
3951 }
3952 if onuGemInfo != nil {
3953 if len(onuGemInfo.UniPorts) == 0 {
3954 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3955 return nil, err
3956 }
3957 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3958 return onuGemInfo, nil
3959 }
3960 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3961 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3962}
3963
3964func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3965 var err error
3966 var allocStats *oop.OnuAllocIdStatistics
3967 var onuGemStats *oop.GemPortStatistics
3968 for _, uni := range onuGemInfo.UniPorts {
3969 uniID := plt.UniIDFromPortNum(uni)
3970 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3971 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3972 if len(tpIDs) == 0 {
3973 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3974 continue
3975 }
3976 for _, tpId := range tpIDs {
3977 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3978 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3979 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3980 if techProfileInstance != nil {
3981 switch tpInst := techProfileInstance.(type) {
3982 case *tp_pb.TechProfileInstance:
3983 allocId := tpInst.UsScheduler.AllocId
3984 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3985 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3986 if err != nil {
3987 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3988 return err
3989 }
3990 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3991 allocIdInfo.AllocId = allocStats.AllocId
3992 allocIdInfo.RxBytes = allocStats.RxBytes
3993
3994 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3995
3996 gemPorts := tpInst.UpstreamGemPortAttributeList
3997 for _, gem := range gemPorts {
3998 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3999 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
4000 if err != nil {
4001 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
4002 return err
4003 }
4004 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
4005 gemStatsInfo.GemId = onuGemStats.GemportId
4006 gemStatsInfo.RxBytes = onuGemStats.RxBytes
4007 gemStatsInfo.RxPackets = onuGemStats.RxPackets
4008 gemStatsInfo.TxBytes = onuGemStats.TxBytes
4009 gemStatsInfo.TxPackets = onuGemStats.TxPackets
4010
4011 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
4012 }
4013 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
4014
4015 default:
4016 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4017 return err
4018 }
4019 } else {
4020 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4021 continue
4022 }
4023 }
4024 }
4025 return err
4026}
4027
4028//nolint:unparam
4029func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4030 singleValResp := extension.SingleGetValueResponse{
4031 Response: &extension.GetValueResponse{
4032 Status: extension.GetValueResponse_OK,
4033 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4034 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4035 },
4036 },
4037 }
4038 errResp := func(status extension.GetValueResponse_Status,
4039 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4040 return &extension.SingleGetValueResponse{
4041 Response: &extension.GetValueResponse{
4042 Status: status,
4043 ErrReason: reason,
4044 },
4045 }
4046 }
4047
4048 var intfID, onuID uint32
4049 if onuDevice != nil {
4050 onuID = onuDevice.ProxyAddress.OnuId
4051 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4052 }
4053
4054 onuKey := dh.formOnuKey(intfID, onuID)
4055 if _, ok := dh.onus.Load(onuKey); !ok {
4056 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4057 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4058 }
4059 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4060
4061 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4062 if err == nil {
4063 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4064 if err != nil {
4065 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4066 }
4067 } else {
4068 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4069 }
4070 return &singleValResp
4071}
4072
nikesh.krishnanc8473432023-06-14 12:14:54 +05304073func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304074 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
4075 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
4076 if err != nil {
4077 return nil, err
4078 }
4079 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304080}
4081
4082func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304083 Intf := oop.Interface{IntfId: intfID}
4084 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
4085 if err != nil {
4086 return nil, err
4087 }
4088 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304089}
4090
Gamze Abaka85e9a142021-05-26 13:41:39 +00004091func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004092 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
4093 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4094 if err != nil {
4095 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4096 return generateSingleGetValueErrorResponse(err)
4097 }
4098 return &extension.SingleGetValueResponse{
4099 Response: &extension.GetValueResponse{
4100 Status: extension.GetValueResponse_OK,
4101 Response: &extension.GetValueResponse_RxPower{
4102 RxPower: &extension.GetRxPowerResponse{
4103 IntfId: rxPowerRequest.IntfId,
4104 OnuId: rxPowerRequest.OnuId,
4105 Status: rxPower.Status,
4106 FailReason: rxPower.FailReason.String(),
4107 RxPower: rxPower.RxPowerMeanDbm,
4108 },
4109 },
4110 },
4111 }
4112}
4113
praneeth nalmas55616d62023-02-06 09:19:18 +05304114func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304115 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304116 return &extension.SingleGetValueResponse{
4117 Response: &extension.GetValueResponse{
4118 Status: status,
4119 ErrReason: reason,
4120 },
4121 }
4122 }
4123
4124 resp := extension.SingleGetValueResponse{
4125 Response: &extension.GetValueResponse{
4126 Status: extension.GetValueResponse_OK,
4127 Response: &extension.GetValueResponse_OltRxPower{
4128 OltRxPower: &extension.GetOltRxPowerResponse{},
4129 },
4130 },
4131 }
4132
4133 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4134 portLabel := OltRxPowerRequest.PortLabel
4135 serialNumber := OltRxPowerRequest.OnuSn
4136
4137 portInfo := strings.Split(portLabel, "-")
4138 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4139
4140 if err != nil {
4141 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4142 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4143 }
4144
4145 if portInfo[0] != "pon" {
4146 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4147 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4148 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304149
4150 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304151 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4152 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304153 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
4154 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4155 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304156 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4157 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304158 }
4159
4160 rxPowerValue := extension.RxPower{}
4161 rxPowerValue.OnuSn = onuDev.serialNumber
4162 rxPowerValue.Status = rxPower.GetStatus()
4163 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4164 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4165
4166 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304167 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304168 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4169 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4170 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304171 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304172 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304173 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304174 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05304175 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4176 if err != nil {
4177 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4178 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304179 rxPowerValue := extension.RxPower{}
4180 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4181 rxPowerValue.Status = rxPower.GetStatus()
4182 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4183 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4184
4185 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4186 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304187 }
4188 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4189 return true
4190 })
4191 }
4192 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4193 return &resp
4194}
4195
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304196func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4197 errResp := func(status extension.GetValueResponse_Status,
4198 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4199 return &extension.SingleGetValueResponse{
4200 Response: &extension.GetValueResponse{
4201 Status: status,
4202 ErrReason: reason,
4203 },
4204 }
4205 }
4206
4207 resp := extension.SingleGetValueResponse{
4208 Response: &extension.GetValueResponse{
4209 Status: extension.GetValueResponse_OK,
4210 Response: &extension.GetValueResponse_OltPonStatsResponse{
4211 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4212 },
4213 },
4214 }
4215
4216 portLabel := ponStatsRequest.GetPortLabel()
4217 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4218
4219 portInfo := strings.Split(portLabel, "-")
4220 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4221
4222 if err != nil {
4223 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4224 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4225 }
4226
4227 if portInfo[0] != "pon" {
4228 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4229 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4230 }
4231
4232 Interface := oop.Interface{IntfId: uint32(portNumber)}
4233 ponStats, err := dh.Client.GetPonPortStatistics(ctx, &Interface)
4234 if err != nil {
4235 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4236 return generateSingleGetValueErrorResponse(err)
4237 }
4238
4239 ponPortStats := resp.Response.GetOltPonStatsResponse()
4240 ponPortStats.PonPort = uint32(portNumber)
4241 ponPortStats.PortStatistics = ponStats
4242
4243 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4244 return &resp
4245}
4246
4247func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4248 errResp := func(status extension.GetValueResponse_Status,
4249 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4250 return &extension.SingleGetValueResponse{
4251 Response: &extension.GetValueResponse{
4252 Status: status,
4253 ErrReason: reason,
4254 },
4255 }
4256 }
4257
4258 resp := extension.SingleGetValueResponse{
4259 Response: &extension.GetValueResponse{
4260 Status: extension.GetValueResponse_OK,
4261 Response: &extension.GetValueResponse_OltNniStatsResponse{
4262 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4263 },
4264 },
4265 }
4266
4267 portLabel := nniStatsRequest.GetPortLabel()
4268 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4269
4270 portInfo := strings.Split(portLabel, "-")
4271 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4272
4273 if err != nil {
4274 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4275 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4276 }
4277
4278 if portInfo[0] != "nni" {
4279 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4280 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4281 }
4282
4283 Interface := oop.Interface{IntfId: uint32(portNumber)}
4284 nniStats, err := dh.Client.GetNniPortStatistics(ctx, &Interface)
4285 if err != nil {
4286 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4287 return generateSingleGetValueErrorResponse(err)
4288 }
4289
4290 nniPortStats := resp.Response.GetOltNniStatsResponse()
4291 nniPortStats.NniPort = uint32(portNumber)
4292 nniPortStats.PortStatistics = nniStats
4293
4294 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4295 return &resp
4296}
4297
Akash Kankanala041a2122024-10-16 15:49:22 +05304298// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004299func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304300 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004301 return &extension.SingleGetValueResponse{
4302 Response: &extension.GetValueResponse{
4303 Status: status,
4304 ErrReason: reason,
4305 },
4306 }
4307 }
4308
4309 if err != nil {
4310 if e, ok := status.FromError(err); ok {
4311 switch e.Code() {
4312 case codes.Internal:
4313 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4314 case codes.DeadlineExceeded:
4315 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4316 case codes.Unimplemented:
4317 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4318 case codes.NotFound:
4319 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4320 }
4321 }
4322 }
4323
4324 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4325}
khenaidoo106c61a2021-08-11 18:05:46 -04004326
4327/*
4328Helper functions to communicate with Core
4329*/
4330
4331func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4332 cClient, err := dh.coreClient.GetCoreServiceClient()
4333 if err != nil || cClient == nil {
4334 return nil, err
4335 }
4336 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4337 defer cancel()
4338 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4339}
4340
khenaidoodc2116e2021-10-19 17:33:19 -04004341func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004342 cClient, err := dh.coreClient.GetCoreServiceClient()
4343 if err != nil || cClient == nil {
4344 return nil, err
4345 }
4346 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4347 defer cancel()
4348 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4349}
4350
khenaidoodc2116e2021-10-19 17:33:19 -04004351func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004352 cClient, err := dh.coreClient.GetCoreServiceClient()
4353 if err != nil || cClient == nil {
4354 return err
4355 }
4356 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4357 defer cancel()
4358 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4359 return err
4360}
4361
4362func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4363 cClient, err := dh.coreClient.GetCoreServiceClient()
4364 if err != nil || cClient == nil {
4365 return nil, err
4366 }
4367 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4368 defer cancel()
4369 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4370}
4371
4372func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4373 cClient, err := dh.coreClient.GetCoreServiceClient()
4374 if err != nil || cClient == nil {
4375 return nil, err
4376 }
4377 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4378 defer cancel()
4379 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4380}
4381
4382func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4383 cClient, err := dh.coreClient.GetCoreServiceClient()
4384 if err != nil || cClient == nil {
4385 return err
4386 }
4387 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4388 defer cancel()
4389 _, err = cClient.DeviceUpdate(subCtx, device)
4390 return err
4391}
4392
khenaidoodc2116e2021-10-19 17:33:19 -04004393func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004394 cClient, err := dh.coreClient.GetCoreServiceClient()
4395 if err != nil || cClient == nil {
4396 return nil, err
4397 }
4398 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4399 defer cancel()
4400 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4401}
4402
khenaidoodc2116e2021-10-19 17:33:19 -04004403func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004404 cClient, err := dh.coreClient.GetCoreServiceClient()
4405 if err != nil || cClient == nil {
4406 return err
4407 }
4408 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4409 defer cancel()
4410 _, err = cClient.SendPacketIn(subCtx, pkt)
4411 return err
4412}
4413
4414func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4415 cClient, err := dh.coreClient.GetCoreServiceClient()
4416 if err != nil || cClient == nil {
4417 return err
4418 }
4419 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4420 defer cancel()
4421 _, err = cClient.PortCreated(subCtx, port)
4422 return err
4423}
4424
khenaidoodc2116e2021-10-19 17:33:19 -04004425func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004426 cClient, err := dh.coreClient.GetCoreServiceClient()
4427 if err != nil || cClient == nil {
4428 return err
4429 }
4430 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4431 defer cancel()
4432 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4433 return err
4434}
4435
khenaidoodc2116e2021-10-19 17:33:19 -04004436func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004437 cClient, err := dh.coreClient.GetCoreServiceClient()
4438 if err != nil || cClient == nil {
4439 return err
4440 }
4441 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4442 defer cancel()
4443 _, err = cClient.PortStateUpdate(subCtx, portState)
4444 return err
4445}
4446
khenaidoodc2116e2021-10-19 17:33:19 -04004447func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004448 cClient, err := dh.coreClient.GetCoreServiceClient()
4449 if err != nil || cClient == nil {
4450 return nil, err
4451 }
4452 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4453 defer cancel()
4454 return cClient.GetDevicePort(subCtx, portFilter)
4455}
4456
nikesh.krishnanc8473432023-06-14 12:14:54 +05304457func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4458 cClient, err := dh.coreClient.GetCoreServiceClient()
4459 if err != nil || cClient == nil {
4460 return nil, err
4461 }
4462 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4463 defer cancel()
4464 return cClient.GetPorts(subCtx, portFilter)
4465}
4466
khenaidoo106c61a2021-08-11 18:05:46 -04004467/*
4468Helper functions to communicate with child adapter
4469*/
4470
khenaidoodc2116e2021-10-19 17:33:19 -04004471func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) 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-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4477 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4478 defer cancel()
4479 _, err = aClient.OmciIndication(subCtx, response)
4480 return err
4481}
4482
khenaidoodc2116e2021-10-19 17:33:19 -04004483func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) 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-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4489 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4490 defer cancel()
4491 _, err = aClient.OnuIndication(subCtx, onuInd)
4492 return err
4493}
4494
khenaidoodc2116e2021-10-19 17:33:19 -04004495func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) 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-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4501 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4502 defer cancel()
4503 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4504 return err
4505}
4506
khenaidoodc2116e2021-10-19 17:33:19 -04004507func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) 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-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4513 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4514 defer cancel()
4515 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4516 return err
4517}
4518
khenaidoodc2116e2021-10-19 17:33:19 -04004519func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004520 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4521 if err != nil || aClient == nil {
4522 return err
4523 }
4524 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4525 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4526 defer cancel()
4527 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4528 return err
4529}
4530
4531/*
4532Helper functions for remote communication
4533*/
4534
4535// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4536// supports is deleted
4537func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4538 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4539
4540 dh.lockChildAdapterClients.Lock()
4541 defer dh.lockChildAdapterClients.Unlock()
4542 if _, ok := dh.childAdapterClients[endpoint]; ok {
4543 // Already set
4544 return nil
4545 }
4546
4547 // Setup child's adapter grpc connection
4548 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004549 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4550 dh.cfg.AdapterEndpoint,
4551 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004552 "onu_inter_adapter_service.OnuInterAdapterService",
4553 dh.onuInterAdapterRestarted,
4554 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004555 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4556 return err
4557 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304558 retryCodes := []codes.Code{
4559 codes.Unavailable, // server is currently unavailable
4560 codes.DeadlineExceeded, // deadline for the operation was exceeded
4561 }
4562 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4563 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 -04004564
nikesh.krishnand9812542023-08-01 18:31:39 +05304565 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004566 // Wait until we have a connection to the child adapter.
4567 // Unlimited retries or until context expires
4568 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4569 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4570 for {
4571 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4572 if err == nil && client != nil {
4573 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4574 break
4575 }
4576 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4577 // Backoff
4578 if err = backoff.Backoff(subCtx); err != nil {
4579 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4580 break
4581 }
4582 }
4583 return nil
4584}
4585
khenaidoodc2116e2021-10-19 17:33:19 -04004586func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004587 // First check from cache
4588 dh.lockChildAdapterClients.RLock()
4589 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4590 dh.lockChildAdapterClients.RUnlock()
4591 return cgClient.GetOnuInterAdapterServiceClient()
4592 }
4593 dh.lockChildAdapterClients.RUnlock()
4594
4595 // Set the child connection - can occur on restarts
4596 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4597 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4598 cancel()
4599 if err != nil {
4600 return nil, err
4601 }
4602
4603 // Get the child client now
4604 dh.lockChildAdapterClients.RLock()
4605 defer dh.lockChildAdapterClients.RUnlock()
4606 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4607 return cgClient.GetOnuInterAdapterServiceClient()
4608 }
4609 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4610}
4611
4612func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4613 dh.lockChildAdapterClients.Lock()
4614 defer dh.lockChildAdapterClients.Unlock()
4615 for key, client := range dh.childAdapterClients {
4616 client.Stop(ctx)
4617 delete(dh.childAdapterClients, key)
4618 }
4619}
4620
khenaidooefff76e2021-12-15 16:51:30 -05004621// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4622func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4623 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004624 return nil
4625}
4626
khenaidooefff76e2021-12-15 16:51:30 -05004627// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4628func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4629 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004630 return nil
4631 }
khenaidooefff76e2021-12-15 16:51:30 -05004632 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004633}
Girish Gowdra950326e2021-11-05 12:43:24 -07004634
4635func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4636 dh.lockDevice.Lock()
4637 defer dh.lockDevice.Unlock()
4638 dh.isDeviceDeletionInProgress = flag
4639}
4640
4641func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4642 dh.lockDevice.RLock()
4643 defer dh.lockDevice.RUnlock()
4644 return dh.isDeviceDeletionInProgress
4645}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004646
4647// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4648// Returns false if waiting timed out.
4649func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4650 c := make(chan struct{})
4651 go func() {
4652 defer close(c)
4653 wg.Wait()
4654 }()
4655 select {
4656 case <-c:
4657 return true // completed normally
4658 case <-time.After(timeout):
4659 return false // timed out
4660 }
4661}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304662
4663func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4664 val, err := json.Marshal(signature)
4665 if err != nil {
4666 logger.Error(ctx, "failed-to-marshal")
4667 return
4668 }
4669 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4670 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4671 }
4672}
4673
4674func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4675 var signature uint32
4676
4677 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4678 if er == nil {
4679 if Value != nil {
4680 Val, er := kvstore.ToByte(Value.Value)
4681 if er != nil {
4682 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4683 return signature
4684 }
4685 if er = json.Unmarshal(Val, &signature); er != nil {
4686 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4687 return signature
4688 }
4689 }
4690 }
4691 return signature
4692}