blob: a72c0118b93050843cb3b841a3feef65c5271f40 [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"
khenaidoo106c61a2021-08-11 18:05:46 -040042 "github.com/opencord/voltha-lib-go/v7/pkg/config"
43 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
44 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
45 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070046 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080048
nikesh.krishnand9812542023-08-01 18:31:39 +053049 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
khenaidoo106c61a2021-08-11 18:05:46 -040050 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053051 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080052 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040053 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040054 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040055 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040056 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
57 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040058 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
59 oop "github.com/opencord/voltha-protos/v5/go/openolt"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +053060 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
khenaidoo106c61a2021-08-11 18:05:46 -040061 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070062 "google.golang.org/grpc"
nikesh.krishnand9812542023-08-01 18:31:39 +053063 codes "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040064 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053065)
66
salmansiddiqui7ac62132019-08-22 03:58:50 +000067// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040068const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080069 InvalidPort = 0xffffffff
70 MaxNumOfGroupHandlerChannels = 256
71
72 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
73 McastFlowOrGroupModify = "McastFlowOrGroupModify"
74 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050075 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010076
77 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053078 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040079)
80
Mahir Gunyela2e68702022-12-07 00:00:42 -080081// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053082type DeviceHandler struct {
Akash Kankanala041a2122024-10-16 15:49:22 +053083 EventProxy eventif.EventProxy
84 Client oop.OpenoltClient
85 cm *config.ConfigManager
86 device *voltha.Device
87 cfg *conf.AdapterFlags
88 coreClient *vgrpc.Client
89 childAdapterClients map[string]*vgrpc.Client
90 openOLT *OpenOLT
91 exitChannel chan struct{}
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 groupMgr *OpenOltGroupMgr
95 eventMgr *OpenOltEventMgr
96 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070097
98 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053099
Akash Kankanala041a2122024-10-16 15:49:22 +0530100 portStats *OpenOltStatisticsMgr
101 metrics *pmmetrics.PmMetrics
102 stopCollector chan bool
103 stopHeartbeatCheck chan bool
104 stopIndications chan bool
105 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
106
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700107 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
108 // if the value is true that means the OnuDiscovery indication
109 // is currently being processed and thus we can ignore concurrent requests
110 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
111 // if we do it means something went wrong and we need to retry
Akash Kankanala041a2122024-10-16 15:49:22 +0530112 discOnus sync.Map
113 onus sync.Map
114 activePorts sync.Map
115 flowMgr []*OpenOltFlowMgr
116 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra491a9c62021-01-06 16:43:07 -0800117
118 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
119 // 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 -0700120 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
121 stopMcastHandlerRoutine []chan bool
122 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000123
Akash Kankanala041a2122024-10-16 15:49:22 +0530124 lockChildAdapterClients sync.RWMutex
125 lockDevice sync.RWMutex
126 perPonOnuIndicationChannelLock sync.Mutex
127
128 totalPonPorts uint32
129 heartbeatSignature uint32
130 isCollectorActive bool
131 isHeartbeatCheckActive bool
132 isReadIndicationRoutineActive bool
133
Gamze Abakac2c32a62021-03-11 11:44:18 +0000134 adapterPreviouslyConnected bool
135 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700136
137 isDeviceDeletionInProgress bool
Nandita Biradar1b590f12024-09-27 10:56:28 +0530138 prevOperStatus common.OperStatus_Types
bseenivaaa9165b2025-09-18 17:28:12 +0530139 collectorWaitGroup sync.WaitGroup
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700140}
141
Mahir Gunyela2e68702022-12-07 00:00:42 -0800142// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700143type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400144 deviceID string
145 deviceType string
146 serialNumber string
Akash Kankanala041a2122024-10-16 15:49:22 +0530147 proxyDeviceID string
148 adapterEndpoint string
khenaidoo106c61a2021-08-11 18:05:46 -0400149 onuID uint32
150 intfID uint32
khenaidoo106c61a2021-08-11 18:05:46 -0400151 losRaised bool
152 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700153}
154
Mahir Gunyelb0046752021-02-26 13:51:05 -0800155type onuIndicationMsg struct {
156 ctx context.Context
157 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800158}
159
160type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800161 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800162 stopChannel chan struct{}
163}
164
Mahir Gunyela2e68702022-12-07 00:00:42 -0800165// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
166// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
167// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
168// 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 -0800169type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400170 ctx context.Context // Flow/group handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400171 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
172 group *of.OfpGroupEntry // Group message (can be nil or valid group)
173 errChan *chan error // channel to report the mcast Flow/group handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530174 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
Girish Gowdra491a9c62021-01-06 16:43:07 -0800175}
176
Naga Manjunath7615e552019-10-11 22:35:47 +0530177var pmNames = []string{
178 "rx_bytes",
179 "rx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530180 "rx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530181 "rx_mcast_packets",
182 "rx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530183 "rx_error_packets",
184 "rx_crc_errors",
185 "rx_packets_dropped",
Naga Manjunath7615e552019-10-11 22:35:47 +0530186 "tx_bytes",
187 "tx_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530188 "tx_ucast_packets",
Naga Manjunath7615e552019-10-11 22:35:47 +0530189 "tx_mcast_packets",
190 "tx_bcast_packets",
akashreddyk302516f2025-11-17 15:18:44 +0530191 "tx_error_packets",
192 "tx_dropped_total",
Naga Manjunath7615e552019-10-11 22:35:47 +0530193}
194
Mahir Gunyela2e68702022-12-07 00:00:42 -0800195// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400196func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700197 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700199 device.deviceType = deviceTp
200 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700201 device.onuID = onuID
202 device.intfID = intfID
203 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530204 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400205 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700206 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530207}
208
Mahir Gunyela2e68702022-12-07 00:00:42 -0800209// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400210func 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 -0700211 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530212 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800213 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400214 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400215 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700216 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700217 dh.device = cloned
218 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500219 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700220 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000221 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
222 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530223 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 -0500224 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800225 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800226 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400227 dh.childAdapterClients = make(map[string]*vgrpc.Client)
228 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300229 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530230 if dh.kvStore == nil {
231 logger.Error(ctx, "Failed to setup KV store")
232 return nil
233 }
234
Girish Gowdra491a9c62021-01-06 16:43:07 -0800235 // Create a slice of buffered channels for handling concurrent mcast flow/group.
236 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700237 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
238 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800239 for i := range dh.incomingMcastFlowOrGroup {
240 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800241 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800242 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
243 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
244 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
245 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700246 dh.mcastHandlerRoutineActive[i] = true
247 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800248 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530249 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700250 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530251}
252
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530253func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
254 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
255 switch storeType {
256 case "etcd":
257 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530258 case "redis":
259 return kvstore.NewRedisClient(address, timeout, false)
260 case "redis-sentinel":
261 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530262 }
263 return nil, errors.New("unsupported-kv-store")
264}
265
266// SetKVClient sets the KV client and return a kv backend
267func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
268 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
269 if err != nil {
270 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
271 return nil
272 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530273 kvbackend := &db.Backend{
274 Client: kvClient,
275 StoreType: backend,
276 Address: addr,
277 Timeout: rsrcMgr.KvstoreTimeout,
278 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
279
280 return kvbackend
281}
282
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000283// CloseKVClient closes open KV clients
284func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
285 if dh.resourceMgr != nil {
286 for _, rscMgr := range dh.resourceMgr {
287 if rscMgr != nil {
288 rscMgr.CloseKVClient(ctx)
289 }
290 }
291 }
292 if dh.flowMgr != nil {
293 for _, flMgr := range dh.flowMgr {
294 if flMgr != nil {
295 flMgr.CloseKVClient(ctx)
296 }
297 }
298 }
299}
300
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530301// start save the device to the data model
302func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700303 dh.lockDevice.Lock()
304 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000305 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700306 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000307 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308}
309
khenaidooefff76e2021-12-15 16:51:30 -0500310// Stop stops the device handler
311func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700312 dh.lockDevice.Lock()
313 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000314 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500315 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400316
khenaidooefff76e2021-12-15 16:51:30 -0500317 // Delete (which will stop also) all grpc connections to the child adapters
318 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000319 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530320}
321
ssiddiqui04386ee2021-08-23 21:58:25 +0530322func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
323 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
324 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
325 if pooledIntfID == intfID {
326 return resourceRanges.GetTechnology()
327 }
328 }
329 }
330 return ""
331}
332
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400333func macifyIP(ip net.IP) string {
334 if len(ip) > 0 {
335 oct1 := strconv.FormatInt(int64(ip[12]), 16)
336 oct2 := strconv.FormatInt(int64(ip[13]), 16)
337 oct3 := strconv.FormatInt(int64(ip[14]), 16)
338 oct4 := strconv.FormatInt(int64(ip[15]), 16)
339 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
340 }
341 return ""
342}
343
Neha Sharma96b7bf22020-06-15 10:37:32 +0000344func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400345 var genmac string
346 var addr net.IP
347 var ips []string
348 var err error
349
Neha Sharma96b7bf22020-06-15 10:37:32 +0000350 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400351
352 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000353 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400354
355 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000356 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400357 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000358 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400359 }
360 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000361 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530362 log.Fields{"host": ips[0],
363 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400364 return genmac, nil
365 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000366 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400367 }
368
369 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000370 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530371 log.Fields{"host": host,
372 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400373 return genmac, nil
374}
375
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530376func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700377 slist := strings.Split(mac, ":")
378 result := make([]uint32, len(slist))
379 var err error
380 var tmp int64
381 for index, val := range slist {
382 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
383 return []uint32{1, 2, 3, 4, 5, 6}
384 }
385 result[index] = uint32(tmp)
386 }
387 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530388}
389
Mahir Gunyela2e68702022-12-07 00:00:42 -0800390// 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 -0800391func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800392 switch portType {
393 case voltha.Port_ETHERNET_NNI:
394 return fmt.Sprintf("nni-%d", portNum), nil
395 case voltha.Port_PON_OLT:
396 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700397 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800398
Girish Kumarf26e4882020-03-05 06:49:10 +0000399 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530400}
401
Elia Battiston596406d2022-02-02 12:19:00 +0100402func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
403 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530404 // In case it was not set in the indication
405 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100406 speedMbps = defaultPortSpeedMbps
407 }
408
409 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
410 switch speedMbps {
411 case 1000000:
412 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
413 case 100000:
414 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
415 case 40000:
416 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
417 case 10000:
418 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
419 case 1000:
420 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
421 case 100:
422 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
423 case 10:
424 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
425 }
426
427 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
428
429 port := &of.OfpPort{
430 HwAddr: macAddressToUint32Array(macAddress),
431 Config: 0,
432 State: uint32(of.OfpPortState_OFPPS_LIVE),
433 Curr: capacity,
434 Advertised: capacity,
435 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530436 CurrSpeed: speedMbps * 1000, // kbps
437 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100438 }
439
440 return port
441}
442
443func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000444 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700445 if state == "up" {
446 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530447 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500448 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700449 } else {
450 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500451 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700453 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400454 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800455 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000456 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400457 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500458
khenaidoo106c61a2021-08-11 18:05:46 -0400459 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400460 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400461 DeviceId: dh.device.Id,
462 Port: portNum,
463 })
464 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000465 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400466 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400467 DeviceId: dh.device.Id,
468 PortType: portType,
469 PortNo: portNum,
470 OperStatus: operStatus})
471 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400472 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
473 "device-id": dh.device.Id,
474 "port-type": portType,
475 "port-number": portNum,
476 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500477 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400478 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500479 }
khenaidoo106c61a2021-08-11 18:05:46 -0400480
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400481 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400482 port = &voltha.Port{
483 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 PortNo: portNum,
485 Label: label,
486 Type: portType,
487 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100488 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700489 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000490 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700491 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400492 err = dh.createPortInCore(ctx, port)
493 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000494 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000496 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400497 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530499 return nil
500}
501
Kent Hagermane6ff1012020-07-14 15:07:53 -0400502func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400503 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530504 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400505 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
506 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530507 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800508 dh.lockDevice.Lock()
509 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530510 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530511}
512
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700513// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530514// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000516 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700517 defer func() {
518 dh.lockDevice.Lock()
519 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530520 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700521 dh.lockDevice.Unlock()
522 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700523 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700524 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700525 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700526 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400527
David Bainbridgef5879ca2019-12-13 21:17:54 +0000528 // Create an exponential backoff around re-enabling indications. The
529 // maximum elapsed time for the back off is set to 0 so that we will
530 // continue to retry. The max interval defaults to 1m, but is set
531 // here for code clarity
532 indicationBackoff := backoff.NewExponentialBackOff()
533 indicationBackoff.MaxElapsedTime = 0
534 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700535
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700536 dh.lockDevice.Lock()
537 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530538 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700539 dh.lockDevice.Unlock()
540
Girish Gowdra3f974912020-03-23 20:35:18 -0700541Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700542 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400543 select {
544 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000545 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700546 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400547 default:
548 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100549
550 select {
551 case <-indications.Context().Done():
552 if err != nil {
553 logger.Warnw(ctx, "error-during-enable-indications",
554 log.Fields{"err": err,
555 "device-id": dh.device.Id})
556 }
557
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400558 // Use an exponential back off to prevent getting into a tight loop
559 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100560 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
561 "device-id": dh.device.Id,
562 "duration": duration,
563 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400564 if duration == backoff.Stop {
565 // If we reach a maximum then warn and reset the backoff
566 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100567 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530568 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530569 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400570 indicationBackoff.Reset()
571 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700572
573 // On failure process a backoff timer while watching for stopIndications
574 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700575 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700576 select {
577 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000578 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700579 if !backoffTimer.Stop() {
580 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700581 }
582 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700583 case <-backoffTimer.C:
584 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700585 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700586 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
587 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400588 }
589 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100590 default:
591 if err != nil {
592 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530593 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530594 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100595 // Close the stream, and re-initialize it
596 if err = indications.CloseSend(); err != nil {
597 // Ok to ignore here, because we landed here due to a problem on the stream
598 // In all probability, the closeSend call may fail
599 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
600 log.Fields{"err": err,
601 "device-id": dh.device.Id})
602 }
603 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
604 return err
605 }
606 // once we re-initialized the indication stream, continue to read indications
607 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700608 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100609 // Reset backoff if we have a successful receive
610 indicationBackoff.Reset()
611 // When OLT is admin down, ignore all indications.
612 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
613 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
614 log.Fields{"indication": indication,
615 "device-id": dh.device.Id})
616 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700617 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100618 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530619 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700620 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700622 // Close the send stream
623 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700624
Girish Gowdra3f974912020-03-23 20:35:18 -0700625 return nil
626}
627
628func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700629 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700630 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
631 if err != nil {
632 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
633 }
634 if indications == nil {
635 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
636 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700637 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700638 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400639}
640
641// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
642func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
643 switch indication.Data.(type) {
644 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
645 return true
646
647 default:
648 return false
649 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650}
651
David K. Bainbridge794735f2020-02-11 21:01:37 -0800652func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700653 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000654 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530655 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530657 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000659 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000660 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530661 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000662 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800663 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000664 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800665 }
666 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667}
668
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530669func (dh *DeviceHandler) handleOnuDisableIndication(ctx context.Context, onuIndication *oop.OnuDisabledIndication) error {
670 logger.Infow(ctx, "handleOnuDisableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
671 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
672 intfID := onuIndication.GetIntfId()
673 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
674 onuDev := dh.getChildDevice(ctx, sn, ponPort)
675 if onuDev == nil {
676 logger.Warnw(ctx, "handleOnuDisableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
677 onuDev = &OnuDevice{
678 serialNumber: sn,
679 }
680 }
681 dh.discOnus.Delete(sn)
682
683 raisedTs := time.Now().Unix()
684 if err := dh.eventMgr.onuDisableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
685 return olterrors.NewErrAdapter("failed-indication", log.Fields{
686 "device-id": dh.device.Id,
687 "indication": onuIndication,
688 "timestamp": raisedTs}, err)
689 }
690 OnuIndication := generateOnuIndication(onuDev.intfID, onuDev.onuID, "down", "down")
691 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDev.adapterEndpoint, &ia.OnuIndicationMessage{
692 DeviceId: onuDev.deviceID,
693 OnuIndication: OnuIndication.GetOnuInd(),
694 })
695 if err != nil {
696 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
697 "onu-indicator": OnuIndication.GetOnuInd(),
698 "source": dh.openOLT.config.AdapterEndpoint,
699 "device-type": onuDev.deviceType,
700 "device-id": onuDev.deviceID}, err)
701 }
702 return nil
703}
704
705func (dh *DeviceHandler) handleOnuEnableIndication(ctx context.Context, onuIndication *oop.OnuEnabledIndication) error {
706 logger.Infow(ctx, "handleOnuEnableIndication", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
707 sn := dh.stringifySerialNumber(onuIndication.SerialNumber)
708 intfID := onuIndication.GetIntfId()
709 ponPort := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
710 onuDev := dh.getChildDevice(ctx, sn, ponPort)
711 if onuDev == nil {
712 logger.Warnw(ctx, "handleOnuEnableIndication onu-device-fetch-failed", log.Fields{"device-id": dh.device.Id, "onuInd": onuIndication})
713 onuDev = &OnuDevice{
714 serialNumber: sn,
715 }
716 }
717 raisedTs := time.Now().Unix()
718
719 if err := dh.eventMgr.onuEnableIndication(ctx, onuIndication, dh.device.Id, onuDev, raisedTs); err != nil {
720 return olterrors.NewErrAdapter("failed-indication", log.Fields{
721 "device-id": dh.device.Id,
722 "indication": onuIndication,
723 "timestamp": raisedTs}, err)
724 }
725 return nil
726}
727
Akash Kankanala041a2122024-10-16 15:49:22 +0530728// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530729func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700730 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700731 switch indication.Data.(type) {
732 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000733 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
734 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700735 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 -0800736 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400737 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800738 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000740 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
741 defer span.Finish()
742
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700743 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800744 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100745 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400746 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800747 }
748 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000749 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700750 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000751 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
752 defer span.Finish()
753
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700754 intfOperInd := indication.GetIntfOperInd()
755 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800756 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100757 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400758 _ = 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 -0800759 }
760 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 } else if intfOperInd.GetType() == "pon" {
762 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
763 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800764 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100765 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400766 _ = 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 -0800767 }
768 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000769 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700770 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000771 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530772 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530773 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000775 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
776 defer span.Finish()
777
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000779 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530780 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800781 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000783 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
784 defer span.Finish()
785
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700786 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000787 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530788 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800789 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700790 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000791 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
792 defer span.Finish()
793
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700794 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000795 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 -0800796 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000797 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400798 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800799 }
800 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000802 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
803 defer span.Finish()
804
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700805 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000806 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700807 "intf-type": pktInd.IntfId,
808 "intf-id": pktInd.IntfId,
809 "gem-port-id": pktInd.GemportId,
810 "port-no": pktInd.PortNo,
811 "device-id": dh.device.Id,
812 })
813
814 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000815 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700816 "intf-type": pktInd.IntfId,
817 "intf-id": pktInd.IntfId,
818 "gem-port-id": pktInd.GemportId,
819 "port-no": pktInd.PortNo,
820 "packet": hex.EncodeToString(pktInd.Pkt),
821 "device-id": dh.device.Id,
822 })
823 }
824
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825 go func() {
826 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400827 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800828 }
829 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700830 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000831 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
832 defer span.Finish()
833
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700834 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700835 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700836 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000837 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
838 defer span.Finish()
839
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000843 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
844 defer span.Finish()
845
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700846 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000847 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
848 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
balaji.nagarajan68f56e82025-07-04 15:16:01 +0530849 case *oop.Indication_OnuDisabledInd:
850 span, ctx := log.CreateChildSpan(ctx, "onu-disable-indication", log.Fields{"device-id": dh.device.Id})
851 defer span.Finish()
852 logger.Infow(ctx, "received onu-disable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
853 if err := dh.handleOnuDisableIndication(ctx, indication.GetOnuDisabledInd()); err != nil {
854 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
855 }
856 case *oop.Indication_OnuEnabledInd:
857 span, ctx := log.CreateChildSpan(ctx, "onu-enable-indication", log.Fields{"device-id": dh.device.Id})
858 defer span.Finish()
859 logger.Infow(ctx, "received onu-enable-indication", log.Fields{"device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()})
860 if err := dh.handleOnuEnableIndication(ctx, indication.GetOnuEnabledInd()); err != nil {
861 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id, "onu-ind": indication.GetOnuInd()}, err).Log()
862 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700863 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530864}
865
nikesh.krishnanc8473432023-06-14 12:14:54 +0530866func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
867 onuInd := &oop.OnuIndication{
868 IntfId: intfID,
869 OnuId: onuID,
870 OperState: operState,
871 AdminState: adminState,
872 }
873 indication := &oop.Indication{
874 Data: &oop.Indication_OnuInd{
875 OnuInd: onuInd,
876 },
877 }
878 return indication
879}
880
881func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
882 onuAlarmInd := &oop.OnuAlarmIndication{
883 IntfId: intfID,
884 OnuId: onuID,
885 LosStatus: losStatus,
886 }
887 alarmInd := &oop.AlarmIndication{
888 Data: &oop.AlarmIndication_OnuAlarmInd{
889 OnuAlarmInd: onuAlarmInd,
890 },
891 }
892 return alarmInd
893}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530894
Akash Kankanala041a2122024-10-16 15:49:22 +0530895func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530896 ponlosAlarmInd := &oop.LosIndication{
897 IntfId: intfID,
898 Status: losStatus,
899 }
900 alarmInd := &oop.AlarmIndication{
901 Data: &oop.AlarmIndication_LosInd{
902 LosInd: ponlosAlarmInd,
903 },
904 }
905 return alarmInd
906}
Akash Kankanala041a2122024-10-16 15:49:22 +0530907
nikesh.krishnanc8473432023-06-14 12:14:54 +0530908func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
909 go func() {
910 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
911 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
912 }
913 }()
914
915 raisedTs := time.Now().Unix()
916 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
917}
918
919func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530920 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
921 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530922 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530923 return err
924 }
925 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530926 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
927 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
928 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
929
930 onuID := onuDeviceFromCore.ProxyAddress.OnuId
931 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
932 if err != nil {
933 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530934 } else {
935 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
936 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
937 switch {
938 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
939 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
940 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
941
942 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530943 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530944 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
945 raisedTs := time.Now().Unix()
946 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
947
948 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
949 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530950 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530951 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530952 return nil
953}
954
955func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
956 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
957 DeviceId: dh.device.Id,
958 PortType: voltha.Port_PON_OLT,
959 })
960 if err != nil {
961 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530962 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530963 }
964 for _, portFromCore := range portsFromCore.Items {
965 portNum := portFromCore.GetPortNo()
966 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
967 portOperStatusFromCore := portFromCore.OperStatus
968 portAdminStateFromCore := portFromCore.AdminState
969 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
970 if err != nil {
971 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
972 } else {
973 portLosFromOlt := ponPortFromOlt.GetLos()
974 portStateFromOlt := ponPortFromOlt.GetState()
975 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
976 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
977 "portStateFromOlt": portStateFromOlt.String(),
978 "portOperStatusFromCore": portOperStatusFromCore.String(),
979 "device-id": dh.device.Id,
980 "port": portNum})
981 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
982 raisedTs := time.Now().Unix()
983 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530984 }
985 switch {
986 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
987 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
988 "portStateFromOlt": portStateFromOlt.String(),
989 "portOperStatusFromCore": portOperStatusFromCore.String(),
990 "device-id": dh.device.Id,
991 "port": portNum})
992 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
993 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
994 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
995 "portStateFromOlt": portStateFromOlt.String(),
996 "portOperStatusFromCore": portOperStatusFromCore.String(),
997 "device-id": dh.device.Id,
998 "port": portNum})
999 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
1000 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
1001 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
1002 "device-id": dh.device.Id,
1003 "port": portNum})
1004 default:
1005 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
1006 "portStateFromOlt": portStateFromOlt.String(),
1007 "portOperStatusFromCore": portOperStatusFromCore.String(),
1008 "device-id": dh.device.Id,
1009 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301010 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301011 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301012 }
nikesh.krishnanc8473432023-06-14 12:14:54 +05301013 return nil
1014}
1015
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301016// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301017func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +05301018 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +05301019 // Declare deviceStateFilter to be used later
1020 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +05301021 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001022 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +05301023 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301024 if err != nil {
1025 return fmt.Errorf("failed to get device from core: %w", err)
1026 }
1027 logger.Info(ctx, "Device state", log.Fields{
1028 "device-id": device.Id,
1029 "CurrOperStatus": device.OperStatus,
1030 "CurrConnStatus": device.ConnectStatus,
1031 })
1032 // Perform cleanup if the device's operational status is REBOOTED
1033 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
1034 // Log the device's operational status if it's REBOOTED
1035 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
1036 "device-id": device.Id,
1037 "OperStatus": device.OperStatus,
1038 })
1039 dh.lockDevice.RLock()
1040 // Stop the read indication only if it the routine is active
1041 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1042 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1043 // on next execution of the readIndication routine.
1044 if dh.isHeartbeatCheckActive {
1045 dh.stopHeartbeatCheck <- true
1046 }
1047 if dh.isReadIndicationRoutineActive {
1048 dh.stopIndications <- true
1049 }
bseenivaaa9165b2025-09-18 17:28:12 +05301050 if dh.isCollectorActive {
1051 dh.stopCollector <- true
1052 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301053 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +05301054 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301055 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
1056 return fmt.Errorf("cleanup device resources failed: %w", err)
1057 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301058 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +05301059 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1060 }
bseenivaaa9165b2025-09-18 17:28:12 +05301061 dh.collectorWaitGroup.Add(1)
1062 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301063 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +05301064 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +05301065 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
1066 // Log the device's operational status if it's RECONCILING
1067 logger.Info(ctx, "Device is being reconciled", log.Fields{
1068 "device-id": device.Id,
1069 "OperStatus": device.OperStatus,
1070 })
1071
1072 // Perform reconciliation steps
1073 err = dh.reconcileOnus(ctx)
1074 if err != nil {
1075 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1076 }
1077 err = dh.reconcilePonPorts(ctx)
1078 if err != nil {
1079 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301080 }
1081 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001082 // instantiate the mcast handler routines.
1083 for i := range dh.incomingMcastFlowOrGroup {
1084 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1085 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1086 if !dh.mcastHandlerRoutineActive[i] {
1087 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1088 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1089 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1090 // for incoming mcast flow/group to be processed serially.
1091 dh.mcastHandlerRoutineActive[i] = true
1092 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1093 }
1094 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301095 // Create DeviceStateFilter with the desired operational and connection statuses
1096 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001097 DeviceId: dh.device.Id,
1098 OperStatus: voltha.OperStatus_ACTIVE,
1099 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301100 }
1101 // Log DeviceStateFilter for debugging purposes
1102 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1103 "DeviceId": deviceStateFilter.DeviceId,
1104 "OperStatus": deviceStateFilter.OperStatus,
1105 "ConnStatus": deviceStateFilter.ConnStatus,
1106 })
1107 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301108 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001109 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001110 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001111
Akash Kankanala041a2122024-10-16 15:49:22 +05301112 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001113 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1114 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301115
1116 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1117 if err != nil {
1118 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1119 }
1120 dh.populateActivePorts(ctx, ports.Items)
1121 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1122 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1123 }
1124
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001125 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001126 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1127
Girish Gowdru0c588b22019-04-23 23:24:56 -04001128 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301129}
1130
1131// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301132func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001133 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001134
khenaidoo106c61a2021-08-11 18:05:46 -04001135 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001136 if err != nil || device == nil {
1137 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001138 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001139 }
1140
1141 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001142
Akash Kankanala041a2122024-10-16 15:49:22 +05301143 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001144 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001145 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001146 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001147 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001148
khenaidoodc2116e2021-10-19 17:33:19 -04001149 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001150 DeviceId: cloned.Id,
1151 OperStatus: cloned.OperStatus,
1152 ConnStatus: cloned.ConnectStatus,
1153 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001154 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001155 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001156
Akash Kankanala041a2122024-10-16 15:49:22 +05301157 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001158 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001159 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001160 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001161 }
1162 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001163 // Update onu state as down in onu adapter
1164 onuInd := oop.OnuIndication{}
1165 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001166
1167 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1168 if err != nil {
1169 return err
1170 }
1171 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001172 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001173 DeviceId: onuDevice.Id,
1174 OnuIndication: &onuInd,
1175 })
1176 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001178 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001179 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 "onu-indicator": onuInd,
1181 "device-type": onuDevice.Type,
1182 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301183 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001184 } else {
1185 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 -07001186 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001187 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001188 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001189 /* Discovered ONUs entries need to be cleared , since after OLT
1190 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301191 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001192 dh.lockDevice.Unlock()
1193
Neha Sharma96b7bf22020-06-15 10:37:32 +00001194 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001195 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301196}
1197
1198// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301199func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001200 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001201
1202 // if the connection is already available, close the previous connection (olt reboot case)
1203 if dh.clientCon != nil {
1204 if err = dh.clientCon.Close(); err != nil {
1205 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1206 } else {
1207 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1208 }
1209 }
1210
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301211 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001212 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001213 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1214 grpc.WithInsecure(),
1215 grpc.WithBlock(),
1216 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001217 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001218 )),
1219 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001220 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001221 )))
1222
1223 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301224 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301225 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001226 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001227 }
Akash Sonif49299a2024-04-25 12:06:37 +05301228 //Setting oper and connection state to RECONCILING and conn state to reachable
1229 cgClient, err := dh.coreClient.GetCoreServiceClient()
1230 if err != nil {
1231 return err
1232 }
1233
1234 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1235 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1236 defer cancel()
1237 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1238 DeviceId: dh.device.Id,
1239 OperStatus: voltha.OperStatus_RECONCILING,
1240 ConnStatus: voltha.ConnectStatus_REACHABLE,
1241 }); err != nil {
1242 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1243 }
1244 // 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
1245 // locally cached copy of the device struct.
1246 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1247 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1248 }
1249
Girish Gowdru0c588b22019-04-23 23:24:56 -04001250 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301251}
1252
1253// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301254func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001255 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301256 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001257 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301258}
1259
1260// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301261func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301262 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001263 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001264
1265 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001266 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301267 if err != nil || device == nil {
1268 /*TODO: needs to handle error scenarios */
1269 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1270 }
1271 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001272 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001273
1274 cloned := proto.Clone(device).(*voltha.Device)
1275 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1276 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1277 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001278
khenaidoodc2116e2021-10-19 17:33:19 -04001279 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001280 DeviceId: cloned.Id,
1281 OperStatus: cloned.OperStatus,
1282 ConnStatus: cloned.ConnectStatus,
1283 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301284 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 -04001285 }
1286
Chaitrashree G S44124192019-08-07 20:21:36 -04001287 // 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 +05301288 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001289 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301290 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001291 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001292 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1293 // all the modules initialized and ready to handle incoming ONUs.
1294
Thomas Lee S985938d2020-05-04 11:40:41 +05301295 err = dh.initializeDeviceHandlerModules(ctx)
1296 if err != nil {
1297 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 -04001298 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001299
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001300 go startHeartbeatCheck(ctx, dh)
1301
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001302 return nil
1303 }
1304
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001305 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301306 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 -04001307 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301308
Neha Sharma96b7bf22020-06-15 10:37:32 +00001309 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001310
1311 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001312 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001313 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001314
1315 go startHeartbeatCheck(ctx, dh)
1316
cuilin20187b2a8c32019-03-26 19:52:28 -07001317 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301318}
1319
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001320func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001321 var err error
1322 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001323
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001324 if dh.flowMgr != nil {
1325 dh.StopAllFlowRoutines(ctx)
1326 }
1327
1328 dh.CloseKVClient(ctx)
1329
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001330 if err != nil {
1331 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1332 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001333 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1334 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301335 // If collector go routine is active, wait for it to stop
1336 dh.lockDevice.RLock()
1337 if dh.isCollectorActive {
1338 dh.lockDevice.RUnlock()
1339 dh.collectorWaitGroup.Wait()
1340 } else {
1341 dh.lockDevice.RUnlock()
1342 }
yasin saplid0566272021-12-21 09:10:30 +00001343 // +1 is for NNI
1344 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1345 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001346 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001347 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1348 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1349 // There is only one NNI manager since multiple NNI is not supported for now
1350 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001351 // Instantiate resource manager
1352 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 -07001353 return olterrors.ErrResourceManagerInstantiating
1354 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001355 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001356 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1357 // the KV store to manage mcast group data. Provide the first instance (0th index)
1358 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1359 return olterrors.ErrGroupManagerInstantiating
1360 }
yasin saplid0566272021-12-21 09:10:30 +00001361 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001362 // Instantiate flow manager
1363 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301364 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001365 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1366 } else {
1367 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001368 }
1369 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001370 /* TODO: Instantiate Alarm , stats , BW managers */
1371 /* Instantiating Event Manager to handle Alarms and KPIs */
1372 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1373
1374 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001376
1377 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001378}
1379
Neha Sharma96b7bf22020-06-15 10:37:32 +00001380func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001381 var err error
1382 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301383 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001384
Neha Sharma8f4e4322020-08-06 10:51:53 +00001385 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001386
1387 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001388 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001389 }
1390 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001391 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001392 }
1393
Neha Sharma96b7bf22020-06-15 10:37:32 +00001394 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001395 dh.device.Root = true
1396 dh.device.Vendor = deviceInfo.Vendor
1397 dh.device.Model = deviceInfo.Model
1398 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1399 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1400 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1401
1402 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001403 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001404 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301405 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001406 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001407 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001408 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001409 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001410 dh.device.MacAddress = genmac
1411 } else {
1412 dh.device.MacAddress = deviceInfo.DeviceId
1413 }
1414
1415 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001416 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001417 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001418 }
1419
1420 return deviceInfo, nil
1421}
1422
Neha Sharma96b7bf22020-06-15 10:37:32 +00001423func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301424 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001425
1426 defer func() {
1427 dh.lockDevice.Lock()
1428 dh.isCollectorActive = false
1429 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301430 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001431 }()
1432
1433 dh.lockDevice.Lock()
1434 dh.isCollectorActive = true
1435 dh.lockDevice.Unlock()
1436
Naga Manjunath7615e552019-10-11 22:35:47 +05301437 for {
1438 select {
1439 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301440 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301441 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001442 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001443
khenaidoo106c61a2021-08-11 18:05:46 -04001444 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001445 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001446 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001447 continue
1448 }
khenaidoo106c61a2021-08-11 18:05:46 -04001449 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301450 // NNI Stats
1451 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001452 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301453 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001454 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001455 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001456 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301457 }
1458 // PON Stats
1459 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001460 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301461 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1462 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001463 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001464 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301465 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001466 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001467
yasin sapli9e4c5092022-02-01 13:52:33 +00001468 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001469 if len(onuGemInfoLst) > 0 {
1470 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001471 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001472 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301473 }
1474 }
1475 }
1476}
1477
Mahir Gunyela2e68702022-12-07 00:00:42 -08001478// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301479func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001480 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001481 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301482 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301483
1484 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001485 cgClient, err := dh.coreClient.GetCoreServiceClient()
1486 if err != nil {
1487 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1488 return
1489 }
1490
1491 // Now, set the initial PM configuration for that device
1492 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001493 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301494 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301495}
1496
Mahir Gunyela2e68702022-12-07 00:00:42 -08001497// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001498func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1499 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001500 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301501 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001502 HwDesc: "open_pon",
1503 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001504 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001505 },
1506 SwitchFeatures: &of.OfpSwitchFeatures{
1507 NBuffers: 256,
1508 NTables: 2,
1509 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1510 of.OfpCapabilities_OFPC_TABLE_STATS |
1511 of.OfpCapabilities_OFPC_PORT_STATS |
1512 of.OfpCapabilities_OFPC_GROUP_STATS),
1513 },
1514 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301515}
1516
khenaidoo106c61a2021-08-11 18:05:46 -04001517// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001518func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001519 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001520 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001521 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001522 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001523 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1524 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()
1525 }
khenaidoo106c61a2021-08-11 18:05:46 -04001526 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001527}
1528
Neha Sharma96b7bf22020-06-15 10:37:32 +00001529func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001530 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 -07001531 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001532 var deviceID string
1533 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001534 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001535
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001536 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001537 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001538 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 -07001539 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1540 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001541
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001542 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301543
1544 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001545 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 -07001546 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001547
khenaidoodc2116e2021-10-19 17:33:19 -04001548 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001549 ParentId: dh.device.Id,
1550 OnuId: omciInd.OnuId,
1551 ParentPortNo: ponPort,
1552 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301554 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001555 "intf-id": omciInd.IntfId,
1556 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001557 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001558 deviceType = onuDevice.Type
1559 deviceID = onuDevice.Id
1560 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001561 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301562 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001563 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001564 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301565 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001566 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 +05301567 deviceType = onuInCache.(*OnuDevice).deviceType
1568 deviceID = onuInCache.(*OnuDevice).deviceID
1569 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001570 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001571 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001572
khenaidoodc2116e2021-10-19 17:33:19 -04001573 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001574 ParentDeviceId: proxyDeviceID,
1575 ChildDeviceId: deviceID,
1576 Message: omciInd.Pkt,
1577 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301578 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001579 "source": dh.openOLT.config.AdapterEndpoint,
1580 "device-type": deviceType,
1581 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001582 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001583 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001584 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001585 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301586}
1587
khenaidoo106c61a2021-08-11 18:05:46 -04001588// //ProcessInterAdapterMessage sends the proxied messages to the target device
1589// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1590// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001591// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001592// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001593// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001594// return dh.handleInterAdapterOmciMsg(ctx, msg)
1595// }
1596// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1597// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001598
kesavandb9f54fd2021-11-25 20:08:04 +05301599// ProxyOmciRequests sends the proxied OMCI message to the target device
1600func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301601 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1602 return status.Error(codes.Unavailable, "OLT unreachable")
1603 }
kesavandb9f54fd2021-11-25 20:08:04 +05301604 if omciMsgs.GetProxyAddress() == nil {
1605 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1606 if err != nil {
1607 return olterrors.NewErrNotFound("onu", log.Fields{
1608 "parent-device-id": dh.device.Id,
1609 "child-device-id": omciMsgs.ChildDeviceId}, err)
1610 }
1611 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1612 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1613 return olterrors.NewErrCommunication("send-failed", log.Fields{
1614 "parent-device-id": dh.device.Id,
1615 "child-device-id": omciMsgs.ChildDeviceId}, err)
1616 }
1617 } else {
1618 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1619 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1620 return olterrors.NewErrCommunication("send-failed", log.Fields{
1621 "parent-device-id": dh.device.Id,
1622 "child-device-id": omciMsgs.ChildDeviceId}, err)
1623 }
1624 }
1625 return nil
1626}
1627
1628func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1629 var intfID uint32
1630 var onuID uint32
1631 var connectStatus common.ConnectStatus_Types
1632 if onuDevice != nil {
1633 intfID = onuDevice.ProxyAddress.GetChannelId()
1634 onuID = onuDevice.ProxyAddress.GetOnuId()
1635 connectStatus = onuDevice.ConnectStatus
1636 } else {
1637 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1638 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1639 connectStatus = omciMsgs.GetConnectStatus()
1640 }
1641 if connectStatus != voltha.ConnectStatus_REACHABLE {
1642 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1643
1644 return olterrors.NewErrCommunication("unreachable", log.Fields{
1645 "intf-id": intfID,
1646 "onu-id": onuID}, nil)
1647 }
1648
1649 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1650 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1651
1652 onuSecOmciMsgList := omciMsgs.GetMessages()
1653
1654 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301655 var omciMessage *oop.OmciMsg
1656 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1657 hex.Encode(hexPkt, onuSecOmciMsg)
1658 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1659
1660 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1661 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1662 //https://jira.opencord.org/browse/VOL-4604
1663 transid := extractOmciTransactionID(onuSecOmciMsg)
1664 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1665 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1666
1667 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1668 if err != nil {
1669 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1670 "intf-id": intfID,
1671 "onu-id": onuID,
1672 "message": omciMessage}, err)
1673 }
1674 }
1675 return nil
1676}
1677
khenaidoo106c61a2021-08-11 18:05:46 -04001678// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001679func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001680 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 -07001681
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301682 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1683 return status.Error(codes.Unavailable, "OLT unreachable")
1684 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001685 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001686 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001687 if err != nil {
1688 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001689 "parent-device-id": dh.device.Id,
1690 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001691 }
khenaidoo106c61a2021-08-11 18:05:46 -04001692 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1693 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001694 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001695 "parent-device-id": dh.device.Id,
1696 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001697 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001698 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001699 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1700 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001701 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001702 "parent-device-id": dh.device.Id,
1703 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001704 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001705 }
1706 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301707}
1708
khenaidoodc2116e2021-10-19 17:33:19 -04001709func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001710 var intfID uint32
1711 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001712 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001713 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001714 intfID = onuDevice.ProxyAddress.GetChannelId()
1715 onuID = onuDevice.ProxyAddress.GetOnuId()
1716 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001717 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001718 intfID = omciMsg.GetProxyAddress().GetChannelId()
1719 onuID = omciMsg.GetProxyAddress().GetOnuId()
1720 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001721 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001722 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723 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 -08001724
Thomas Lee S94109f12020-03-03 16:39:29 +05301725 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001726 "intf-id": intfID,
1727 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001728 }
1729
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001730 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1731 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301732 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001733 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001734 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1735 hex.Encode(hexPkt, omciMsg.Message)
1736 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1737
1738 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1739 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1740 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001741 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001742 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001743
Neha Sharma8f4e4322020-08-06 10:51:53 +00001744 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001745 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301746 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001747 "intf-id": intfID,
1748 "onu-id": onuID,
1749 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001750 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001751 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001752}
1753
David K. Bainbridge794735f2020-02-11 21:01:37 -08001754func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301755 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 +00001756 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001757 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001758 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001759 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301760 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301761 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001762 st, _ := status.FromError(err)
1763 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 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 -04001765 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301766 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001767 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001768 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001770 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001771 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001772}
1773
Mahir Gunyela2e68702022-12-07 00:00:42 -08001774// getChildDevice function can be used in general to get child device, if not found in cache the function will
1775// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301776func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1777 var InCacheOnuDev *OnuDevice
1778 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1779 if onuInCache.(*OnuDevice).serialNumber == sn {
1780 InCacheOnuDev = onuInCache.(*OnuDevice)
1781 return false
1782 }
1783 return true
1784 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301785 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301786 if InCacheOnuDev != nil {
1787 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1788 return InCacheOnuDev
1789 }
1790 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1791 ParentId: dh.device.Id,
1792 SerialNumber: sn,
1793 ParentPortNo: parentPortNo,
1794 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301795 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301796 if onuDevice == nil {
1797 return nil
1798 }
1799 onuID := onuDevice.ProxyAddress.OnuId
1800 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1801 onuKey := dh.formOnuKey(intfID, onuID)
1802
1803 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1804 dh.onus.Store(onuKey, onuDev)
1805 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1806 return onuDev
1807}
1808
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301809// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1810// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301811func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001812 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301813 // 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 +05301814 // 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 +05301815 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1816 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1817 ParentId: dh.device.Id,
1818 SerialNumber: sn,
1819 ParentPortNo: parentPortNo,
1820 })
1821 if onuDevice != nil {
1822 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1823 return true, nil
1824 }
1825 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1826
1827 return false, nil
1828 } else {
1829 tpInstExists := false
1830 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301831 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1832 if onuDev != nil {
1833 var onuGemInfo *rsrcMgr.OnuGemInfo
1834 var err error
1835 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1836 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1837 return false, err
1838 }
1839 if onuGemInfo != nil {
1840 for _, uni := range onuGemInfo.UniPorts {
1841 uniID := plt.UniIDFromPortNum(uni)
1842 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1843 if len(tpIDs) != 0 {
1844 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1845 tpInstExists = true
1846 break
1847 }
1848 }
1849 }
1850 }
1851 return tpInstExists, nil
1852 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301853}
1854
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001855// processDiscONULOSClear clears the LOS Alarm if it's needed
1856func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301857 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001858 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301859
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001860 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1861 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1862 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1863 OnuLosRaise event sent for it */
1864 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1865 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1866 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1867 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1868 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1869 "currentIntfId": onuDiscInd.GetIntfId()})
1870 // TODO:: Should we need to ignore raising OnuLosClear event
1871 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301872 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001873 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1874 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1875 alarmInd.LosStatus = statusCheckOff
1876 go func() {
1877 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1878 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1879 }
1880 }()
1881 // stop iterating
1882 return false
1883 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301884 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001885 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301886}
1887
bseeniva43b5a912025-06-05 12:48:15 +05301888func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1889 if err != nil || tpInstExists {
1890 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1891 } else {
1892 // once the function completes set the value to false so that
1893 // we know the processing has inProcess.
1894 // Note that this is done after checking if we are already processing
1895 // to avoid changing the value from a different thread
1896 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1897 dh.discOnus.Store(sn, false)
1898 }
1899}
1900
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301901func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301902 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301903 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301904
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301905 channelID := onuDiscInd.GetIntfId()
1906 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1907
1908 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301909 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301910 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301911 }()
1912
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301913 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1914
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301915 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1916 if !dh.cfg.ForceOnuDiscIndProcessing {
1917 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1918 if error != nil {
1919 return error
1920 }
1921 if tpInstExists {
1922 // ignore the discovery if tpinstance is present.
1923 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1924 return nil
1925 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001926 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001927 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1928
1929 // if the ONU existed, handle the LOS Alarm
1930 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001931 if inProcess.(bool) {
1932 // if we're currently processing the ONU on a different thread, do nothing
1933 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1934 return nil
1935 }
1936 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1937 // then continue processing it
1938 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1939
1940 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001941 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301942 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001943 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001944
1945 // check the ONU is already know to the OLT
1946 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301947 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001948 ParentId: dh.device.Id,
1949 SerialNumber: sn,
1950 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001951
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301952 if error != nil {
1953 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1954 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001955 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 -08001956 switch e.Code() {
1957 case codes.Internal:
1958 // this probably means NOT FOUND, so just create a new device
1959 onuDevice = nil
1960 case codes.DeadlineExceeded:
1961 // if the call times out, cleanup and exit
1962 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301963 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1964 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001965 }
1966 }
1967 }
1968
1969 if onuDevice == nil {
1970 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001971 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001972 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001973 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301974 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001976
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301977 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001978 // if we can't create an ID in resource manager,
1979 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001980 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301981
1982 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001983 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301984 "serial-number": sn}, error)
1985 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001986 }
1987
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301988 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001989 ParentId: dh.device.Id,
1990 ParentPortNo: parentPortNo,
1991 ChannelId: channelID,
1992 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1993 SerialNumber: sn,
1994 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301995 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001996 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001997 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 +05301998
1999 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002000 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302001 "serial-number": sn}, error)
2002 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08002003 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302004 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 +05302005 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
2006 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
2007 "onu-id": onuID,
2008 "device-id": dh.device.Id,
2009 "serial-number": sn}, error)
2010 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002011 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002012 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05302013 log.Fields{"onuDevice": onuDevice,
2014 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07002015 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302016 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04002017 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08002018
khenaidoo106c61a2021-08-11 18:05:46 -04002019 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
2020 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302021 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04002022 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302023 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302024 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
2025 return error
khenaidoo106c61a2021-08-11 18:05:46 -04002026 }
2027
Matteo Scandolo945e4012019-12-12 14:16:11 -08002028 // we can now use the existing ONU Id
2029 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05302030 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002031 //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 +00002032 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07002033 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302034 "intfId": onuDiscInd.GetIntfId(),
2035 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002036 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04002037
khenaidoo106c61a2021-08-11 18:05:46 -04002038 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302039 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002040 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05302041 log.Fields{"onu": onuDev,
2042 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04002043
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302044 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002045 DeviceId: onuDevice.Id,
2046 ParentDeviceId: dh.device.Id,
2047 OperStatus: common.OperStatus_DISCOVERED,
2048 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302049 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302050 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002051 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302052 "serial-number": sn}, error)
2053 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07002054 }
khenaidoo106c61a2021-08-11 18:05:46 -04002055
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302057 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302058 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002059 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05302060 "serial-number": sn}, error)
2061 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08002062 }
2063 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002064}
2065
Mahir Gunyelb0046752021-02-26 13:51:05 -08002066func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002067 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07002068 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002069 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07002070 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00002071 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05302072 log.Fields{"onuId": onuInd.OnuId,
2073 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05302074 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07002075 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08002076 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002077 errFields := log.Fields{"device-id": dh.device.Id}
2078
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302079 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302080 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002081 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002082 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002083 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002084 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302085 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002086 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002088 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002089 errFields["onu-id"] = onuInd.OnuId
2090 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002091 }
khenaidoodc2116e2021-10-19 17:33:19 -04002092 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002093 ParentId: dh.device.Id,
2094 SerialNumber: serialNumber,
2095 OnuId: onuInd.OnuId,
2096 ParentPortNo: ponPort,
2097 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002098 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002099
David K. Bainbridge794735f2020-02-11 21:01:37 -08002100 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002101 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002102 }
2103
David K. Bainbridge794735f2020-02-11 21:01:37 -08002104 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002105 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002106 "previousIntfId": onuDevice.ParentPortNo,
2107 "currentIntfId": ponPort})
2108 }
2109
2110 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302112 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2113 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302114 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002115 }
2116 if !foundInCache {
2117 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002118 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 -08002119 }
kesavand7cf3a052020-08-28 12:49:18 +05302120 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002121 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002122 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302123 }
2124 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002126 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002127 }
2128 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002129}
2130
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002132 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 -07002133 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2134 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2135 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2136 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002137 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002138 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2139 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002140 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002141 onuInd.OperState = "down"
2142 }
2143 }
2144
David K. Bainbridge794735f2020-02-11 21:01:37 -08002145 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002146 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002147 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 -04002148
khenaidoodc2116e2021-10-19 17:33:19 -04002149 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002150 DeviceId: onuDevice.Id,
2151 OnuIndication: onuInd,
2152 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002153 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302154 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002155 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002156 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002157 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002158 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002159 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002160 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002161 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002162 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002163 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002164}
2165
cuilin20187b2a8c32019-03-26 19:52:28 -07002166func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2167 if serialNum != nil {
2168 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002169 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002170 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002171}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002172func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2173 decodedStr, err := hex.DecodeString(serialNum[4:])
2174 if err != nil {
2175 return nil, err
2176 }
2177 return &oop.SerialNumber{
2178 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002179 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002180 }, nil
2181}
cuilin20187b2a8c32019-03-26 19:52:28 -07002182
2183func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002184 if len(vendorSpecific) > 3 {
2185 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2186 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2187 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2188 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2189 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2190 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2191 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2192 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2193 return tmp
2194 }
2195 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002196}
2197
Mahir Gunyela2e68702022-12-07 00:00:42 -08002198// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002199func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302200 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002201}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002202
Mahir Gunyela2e68702022-12-07 00:00:42 -08002203// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002204func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2205 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302206 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002207 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302208 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002209
khenaidoodc2116e2021-10-19 17:33:19 -04002210 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002211 ParentId: dh.device.Id,
2212 OnuId: onuID,
2213 ParentPortNo: parentPort,
2214 })
2215
Girish Gowdru0c588b22019-04-23 23:24:56 -04002216 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002217 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002218 "intf-id": parentPort,
2219 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002220 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221 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 -08002222 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302223}
2224
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002225// SendPacketInToCore sends packet-in to core
2226// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2227// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002228func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002229 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002230 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002231 "port": logicalPort,
2232 "packet": hex.EncodeToString(packetPayload),
2233 "device-id": dh.device.Id,
2234 })
2235 }
khenaidoo106c61a2021-08-11 18:05:46 -04002236
khenaidoodc2116e2021-10-19 17:33:19 -04002237 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002238 DeviceId: dh.device.Id,
2239 Port: logicalPort,
2240 Packet: packetPayload,
2241 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302242 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002243 "source": "adapter",
2244 "destination": "core",
2245 "device-id": dh.device.Id,
2246 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002247 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002248 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002249 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002250 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002251 "packet": hex.EncodeToString(packetPayload),
2252 "device-id": dh.device.Id,
2253 })
2254 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002255 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002256}
2257
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002258// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002259func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002260 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002261
2262 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2263 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002265 }
2266
Kent Hagermane6ff1012020-07-14 15:07:53 -04002267 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002268 metrics := dh.metrics.GetSubscriberMetrics()
2269 for _, m := range pmConfigs.Metrics {
2270 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002271 }
2272 }
2273}
2274
khenaidoodc2116e2021-10-19 17:33:19 -04002275func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002276 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002277 var errorsList []error
2278
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002279 if dh.getDeviceDeletionInProgressFlag() {
2280 // The device itself is going to be reset as part of deletion. So nothing to be done.
2281 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2282 return nil
2283 }
2284
Girish Gowdru0c588b22019-04-23 23:24:56 -04002285 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002286 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302287 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002288
Neha Sharma96b7bf22020-06-15 10:37:32 +00002289 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302290 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002291 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302292 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002293 if flow_utils.HasGroup(flow) {
2294 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2295 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002296 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2297 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2298 } else {
2299 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2300 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002301 }
Girish Gowdracefae192020-03-19 18:14:10 -07002302 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002303 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302304 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002305 logger.Warnw(ctx, "flow-to-remove-not-found",
2306 log.Fields{
2307 "ponIf": intfID,
2308 "flowToRemove": flow,
2309 "error": err,
2310 })
2311 } else {
2312 errorsList = append(errorsList, err)
2313 }
Girish Gowdracefae192020-03-19 18:14:10 -07002314 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002315 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302316
2317 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302318 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002319 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302320 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002321 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302322 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002323 if flow_utils.HasGroup(flow) {
2324 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2325 } else {
yasin saplid0566272021-12-21 09:10:30 +00002326 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002327 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2328 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2329 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2330 } else {
yasin saplid0566272021-12-21 09:10:30 +00002331 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002332 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002333 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002334 if err != nil {
2335 errorsList = append(errorsList, err)
2336 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302337 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002338 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002339
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002340 return errorsList
2341}
2342
2343func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2344 var err error
2345 var errorsList []error
2346
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002347 if dh.getDeviceDeletionInProgressFlag() {
2348 // The device itself is going to be reset as part of deletion. So nothing to be done.
2349 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2350 return nil
2351 }
2352
Girish Gowdracefae192020-03-19 18:14:10 -07002353 // 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 +00002354 if groups != nil {
2355 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002356 // err = dh.groupMgr.AddGroup(ctx, group)
2357 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002358 if err != nil {
2359 errorsList = append(errorsList, err)
2360 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 }
2362 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002363 // err = dh.groupMgr.ModifyGroup(ctx, group)
2364 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002365 if err != nil {
2366 errorsList = append(errorsList, err)
2367 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002368 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002369 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002370 // err = dh.groupMgr.DeleteGroup(ctx, group)
2371 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002372 if err != nil {
2373 errorsList = append(errorsList, err)
2374 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002375 }
2376 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002377
2378 return errorsList
2379}
2380
Mahir Gunyela2e68702022-12-07 00:00:42 -08002381// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002382func (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 -07002383 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002384
2385 if dh.getDeviceDeletionInProgressFlag() {
2386 // The device itself is going to be reset as part of deletion. So nothing to be done.
2387 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2388 return nil
2389 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302390 if dh.transitionMap.currentDeviceState != deviceStateUp {
2391 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2392 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2393 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002394 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2395 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2396 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002397 if len(errorsList) > 0 {
2398 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2399 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002400 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002401 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302402}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002403
Mahir Gunyela2e68702022-12-07 00:00:42 -08002404// DisableDevice disables the given device
2405// It marks the following for the given device:
2406// Device-Handler Admin-State : down
2407// Device Port-State: UNKNOWN
2408// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002409func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002410 /* On device disable ,admin state update has to be done prior sending request to agent since
2411 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002412 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002413 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002414 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002415 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002416 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002417 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002418 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002420 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002421 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302422
2423 dh.discOnus = sync.Map{}
2424 dh.onus = sync.Map{}
2425
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002426 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302427 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002428 if dh.isCollectorActive {
2429 dh.stopCollector <- true
2430 }
2431 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302432
Neha Sharma96b7bf22020-06-15 10:37:32 +00002433 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002434 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302435 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302436 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002437
kdarapu1afeceb2020-02-12 01:38:09 -05002438 // 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 -04002439 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002440 DeviceId: cloned.Id,
2441 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2442 OperStatus: voltha.OperStatus_UNKNOWN,
2443 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002444 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002445 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002447 return nil
2448}
2449
Neha Sharma96b7bf22020-06-15 10:37:32 +00002450func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002451 // Update onu state as unreachable in onu adapter
2452 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302453 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002454
Akash Kankanala041a2122024-10-16 15:49:22 +05302455 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002456 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002457 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002458 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 -04002459 }
2460 if onuDevices != nil {
2461 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002462 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002463 DeviceId: onuDevice.Id,
2464 OnuIndication: &onuInd,
2465 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002466 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002467 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002468 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002469 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002470 }
2471 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002472}
2473
Mahir Gunyela2e68702022-12-07 00:00:42 -08002474// ReenableDevice re-enables the olt device after disable
2475// It marks the following for the given device:
2476// Device-Handler Admin-State : up
2477// Device Port-State: ACTIVE
2478// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002479func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302480 if dh.Client != nil {
2481 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2482 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2483 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2484 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302485 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302486 } else {
2487 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 +05302488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002489 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002490
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002491 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002492 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002493 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002494 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002495 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2496 } else {
2497 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2498 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2499 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002500 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002501 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302502 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002503 device.OperStatus = voltha.OperStatus_ACTIVE
2504 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302505 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002506 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002507 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002508 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002509
khenaidoodc2116e2021-10-19 17:33:19 -04002510 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002511 DeviceId: device.Id,
2512 OperStatus: device.OperStatus,
2513 ConnStatus: device.ConnectStatus,
2514 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302515 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002516 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002517 "connect-status": device.ConnectStatus,
2518 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002519 }
kesavand39e0aa32020-01-28 20:58:50 -05002520
Neha Sharma96b7bf22020-06-15 10:37:32 +00002521 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002522
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002523 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002524}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002525
npujarec5762e2020-01-01 14:08:48 +05302526func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002527 var uniID uint32
2528 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002529 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302530 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002531 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002532 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002533 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002534 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2535 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2536 } else {
2537 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2538 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002539 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002540 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002541 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002542 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002543 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002544 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002545 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002546 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002547 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002548 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002549 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002550 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002551 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002552 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002553 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002554 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302555 }
yasin saplibddc2d72022-02-08 13:10:17 +00002556 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2557 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002558 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002559 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302560 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002561 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002562 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002563 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 -03002564 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002565 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002566 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002567 if len(errs) > 0 {
2568 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2569 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2570 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002571 return nil
2572}
2573
Devmalya Paul495b94a2019-08-27 19:42:00 -04002574// 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 +05302575func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002576 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002577 /* Clear the KV store data associated with the all the UNI ports
2578 This clears up flow data and also resource map data for various
2579 other pon resources like alloc_id and gemport_id
2580 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002581
2582 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002583 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002584
Himani Chawla49a5d562020-11-25 11:53:44 +05302585 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002586 // Stop the Stats collector
2587 if dh.isCollectorActive {
2588 dh.stopCollector <- true
2589 }
2590 // stop the heartbeat check routine
2591 if dh.isHeartbeatCheckActive {
2592 dh.stopHeartbeatCheck <- true
2593 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302594 // Stop the read indication only if it the routine is active
2595 if dh.isReadIndicationRoutineActive {
2596 dh.stopIndications <- true
2597 }
2598 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302599
2600 err := dh.cleanupDeviceResources(ctx)
2601 if err != nil {
2602 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2603 } else {
2604 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2605 }
2606
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002607 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302608 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002609 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302610 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002611 go func() {
2612 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302613 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2614 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002615 }
2616 }()
2617 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002618 }
2619 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002620 // There is no need to update the core about operation status and connection status of the OLT.
2621 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2622 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2623 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002624
khenaidoo7eb2d672021-10-22 19:08:50 -04002625 // Stop the adapter grpc clients for that parent device
2626 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002627 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002628}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002629
2630// StopAllFlowRoutines stops all flow routines
2631func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2632 var wg sync.WaitGroup
2633 wg.Add(1) // for the mcast routine below to finish
2634 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2635 for _, flMgr := range dh.flowMgr {
2636 if flMgr != nil {
2637 wg.Add(1) // for the flow handler routine below to finish
2638 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2639 }
2640 }
2641 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2642 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2643 } else {
2644 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2645 }
2646}
2647
Gustavo Silva41af9122022-10-11 11:05:13 -03002648func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2649 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002650 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302651 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002652 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002653 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002654 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002655 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002656 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2657 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302658 }
2659 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002660 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2661 errs = append(errs, err)
2662 }
2663 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2664 errs = append(errs, err)
2665 }
2666 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2667 errs = append(errs, err)
2668 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002669 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002670 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002671 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002672 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002673 }
2674 // Clean up NNI manager's data
2675 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2676 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002677 }
A R Karthick1f85b802019-10-11 05:06:05 +00002678
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002679 dh.CloseKVClient(ctx)
2680
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002681 // Take one final sweep at cleaning up KV store for the OLT device
2682 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002683 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2684 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002685 }
2686
Devmalya Paul495b94a2019-08-27 19:42:00 -04002687 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302688 dh.onus.Range(func(key interface{}, value interface{}) bool {
2689 dh.onus.Delete(key)
2690 return true
2691 })
2692
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002693 /*Delete discovered ONU map for the device*/
2694 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2695 dh.discOnus.Delete(key)
2696 return true
2697 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002698 if len(errs) > 0 {
2699 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2700 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2701 }
2702 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002703}
2704
Mahir Gunyela2e68702022-12-07 00:00:42 -08002705// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002706func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302707 if dh.Client != nil {
2708 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2709 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2710 }
2711 } else {
2712 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 -04002713 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302714
Neha Sharma96b7bf22020-06-15 10:37:32 +00002715 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002716 return nil
2717}
2718
David K. Bainbridge794735f2020-02-11 21:01:37 -08002719func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002720 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002721 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002722 "packet-indication": *packetIn,
2723 "device-id": dh.device.Id,
2724 "packet": hex.EncodeToString(packetIn.Pkt),
2725 })
2726 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002727 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2728 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2729 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002730 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002731 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002732 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002733 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002734 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002735 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002736 "logical-port-num": logicalPortNum,
2737 "device-id": dh.device.Id,
2738 "packet": hex.EncodeToString(packetIn.Pkt),
2739 })
2740 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002741
khenaidoodc2116e2021-10-19 17:33:19 -04002742 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002743 DeviceId: dh.device.Id,
2744 Port: logicalPortNum,
2745 Packet: packetIn.Pkt,
2746 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302747 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002748 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302749 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002750 "device-id": dh.device.Id,
2751 "packet": hex.EncodeToString(packetIn.Pkt),
2752 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002754
Matteo Scandolo92186242020-06-12 10:54:18 -07002755 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002756 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002757 "packet": hex.EncodeToString(packetIn.Pkt),
2758 "device-id": dh.device.Id,
2759 })
2760 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002761 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002762}
2763
Mahir Gunyela2e68702022-12-07 00:00:42 -08002764// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2765func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2766 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2767 if err != nil {
2768 return olterrors.NewErrInvalidValue(log.Fields{
2769 "egress-nni-port": egressPortNo,
2770 "device-id": dh.device.Id,
2771 }, err)
2772 }
2773 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2774
2775 if logger.V(log.DebugLevel) {
2776 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2777 "uplink-pkt": uplinkPkt,
2778 "packet": hex.EncodeToString(packet.Data),
2779 "device-id": dh.device.Id,
2780 })
2781 }
2782
2783 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2784 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2785 "packet": hex.EncodeToString(packet.Data),
2786 "device-id": dh.device.Id,
2787 }, err)
2788 }
2789 return nil
2790}
2791
2792// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2793func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2794 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2795 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2796 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2797 // Do not packet-out lldp packets on uni port.
2798 // ONOS has no clue about uni/nni ports, it just packets out on all
2799 // available ports on the Logical Switch. It should not be interested
2800 // in the UNI links.
2801 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2802 "device-id": dh.device.Id,
2803 })
2804 return nil
2805 }
2806 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2807 if innerEthType == 0x8100 {
2808 // q-in-q 802.1ad or 802.1q double tagged packet.
2809 // slice out the outer tag.
2810 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2811 if logger.V(log.DebugLevel) {
2812 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2813 "packet-data": hex.EncodeToString(packet.Data),
2814 "device-id": dh.device.Id,
2815 })
2816 }
2817 }
2818 }
2819 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2820 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2821 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2822 var gemPortID uint32
2823 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2824 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2825 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2826 }
2827 if err != nil {
2828 // In this case the openolt agent will receive the gemPortID as 0.
2829 // The agent tries to retrieve the gemPortID in this case.
2830 // This may not always succeed at the agent and packetOut may fail.
2831 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2832 "intf-id": intfID,
2833 "onu-id": onuID,
2834 "uni-id": uniID,
2835 "packet": hex.EncodeToString(packet.Data),
2836 "device-id": dh.device.Id,
2837 "error": err,
2838 })
2839 }
2840
2841 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2842 if logger.V(log.DebugLevel) {
2843 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2844 "egress-port-no": egressPortNo,
2845 "intf-id": intfID,
2846 "onu-id": onuID,
2847 "uni-id": uniID,
2848 "gem-port-id": gemPortID,
2849 "packet": hex.EncodeToString(packet.Data),
2850 "device-id": dh.device.Id,
2851 })
2852 }
2853
2854 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2855 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2856 "source": "adapter",
2857 "destination": "onu",
2858 "egress-port-number": egressPortNo,
2859 "intf-id": intfID,
2860 "oni-id": onuID,
2861 "uni-id": uniID,
2862 "gem-port-id": gemPortID,
2863 "packet": hex.EncodeToString(packet.Data),
2864 "device-id": dh.device.Id,
2865 }, err)
2866 }
2867 return nil
2868}
2869
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002870// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002871func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002872 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002873 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002874 "device-id": dh.device.Id,
2875 "egress-port-no": egressPortNo,
2876 "pkt-length": len(packet.Data),
2877 "packet": hex.EncodeToString(packet.Data),
2878 })
2879 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002880
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002881 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002882 var err error
mgouda86543582025-10-29 20:58:16 +05302883 switch egressPortType {
2884 case voltha.Port_ETHERNET_UNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002885 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302886 case voltha.Port_ETHERNET_NNI:
Mahir Gunyela2e68702022-12-07 00:00:42 -08002887 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
mgouda86543582025-10-29 20:58:16 +05302888 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002889 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302890 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002891 "egressPortType": egressPortType,
2892 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302893 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002894 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002895 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002896 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002897}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002898
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002899func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2900 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002901}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302902
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002903func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002904 defer func() {
2905 dh.lockDevice.Lock()
2906 dh.isHeartbeatCheckActive = false
2907 dh.lockDevice.Unlock()
2908 }()
2909
2910 dh.lockDevice.Lock()
2911 dh.isHeartbeatCheckActive = true
2912 dh.lockDevice.Unlock()
2913
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302914 // start the heartbeat check towards the OLT.
2915 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302916 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302917
2918 for {
2919 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2920 select {
2921 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002922 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002923 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002924 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302925 if timerCheck == nil {
2926 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002927 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302928 }
2929 } else {
2930 if timerCheck != nil {
2931 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002932 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302933 }
2934 timerCheck = nil
2935 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302936 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2937 if dh.heartbeatSignature == 0 {
2938 // First time the signature will be 0, update the signture to DB when not found.
2939 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2940 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2941 }
2942 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2943
2944 dh.lockDevice.RLock()
2945 // Stop the read indication only if it the routine is active
2946 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2947 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2948 // on next execution of the readIndication routine.
2949 if !dh.isReadIndicationRoutineActive {
2950 // Start reading indications
2951 go func() {
2952 if err = dh.readIndications(ctx); err != nil {
2953 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2954 }
2955 }()
2956 }
2957 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302958 } else {
2959 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2960 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2961 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2962 go dh.updateStateRebooted(ctx)
2963 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302964 }
2965 cancel()
2966 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002967 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302968 return
2969 }
2970 }
2971}
2972
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002973func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002974 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002975 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002976 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2977 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2978 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2979 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2980 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002981 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002982 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2983 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002984 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302985
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302986 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002987 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002988 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002989 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002990 DeviceId: dh.device.Id,
2991 OperStatus: voltha.OperStatus_UNKNOWN,
2992 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2993 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002994 _ = 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 -04002995 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302996 /*
2997 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2998 DeviceId: dh.device.Id,
2999 PortTypeFilter: 0,
3000 OperStatus: voltha.OperStatus_UNKNOWN,
3001 }); err != nil {
3002 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
3003 }
3004 */
Gamze Abaka07868a52020-12-17 14:19:28 +00003005
Akash Kankanala041a2122024-10-16 15:49:22 +05303006 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07003007 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04003008 cloned := proto.Clone(device).(*voltha.Device)
3009 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3010 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3011 dh.device = cloned // update local copy of the device
3012 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00003013
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003014 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003015 // Stop the Stats collector
3016 if dh.isCollectorActive {
3017 dh.stopCollector <- true
3018 }
3019 // stop the heartbeat check routine
3020 if dh.isHeartbeatCheckActive {
3021 dh.stopHeartbeatCheck <- true
3022 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07003023 // Stop the read indication only if it the routine is active
3024 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3025 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3026 // on next execution of the readIndication routine.
3027 if dh.isReadIndicationRoutineActive {
3028 dh.stopIndications <- true
3029 }
3030 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04003031 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05303032 }
3033}
kesavand39e0aa32020-01-28 20:58:50 -05003034
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303035func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
3036 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
3037 if err != nil || device == nil {
3038 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
3039 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
3040 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
3041 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
3042 // cleanup in the adapter was already done during DeleteDevice API handler routine.
3043 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
3044 // Immediately return, otherwise accessing a null 'device' struct would cause panic
3045 return
3046 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303047 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07003048 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303049
3050 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
3051 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05303052 // First, stop the read indication and heartbeat check routines to prevent any delay
3053 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303054 dh.lockDevice.RLock()
3055 // Stop the read indication only if it the routine is active
3056 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
3057 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
3058 // on next execution of the readIndication routine.
3059 if dh.isReadIndicationRoutineActive {
3060 dh.stopIndications <- true
3061 }
3062 dh.lockDevice.RUnlock()
3063
bseenivad1c984b2025-01-09 12:54:44 +05303064 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
3065 DeviceId: dh.device.Id,
3066 OperStatus: voltha.OperStatus_REBOOTED,
3067 ConnStatus: voltha.ConnectStatus_REACHABLE,
3068 }); err != nil {
3069 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
3070 }
3071
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303072 //raise olt communication failure event
3073 raisedTs := time.Now().Unix()
3074 cloned := proto.Clone(device).(*voltha.Device)
3075 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3076 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3077 dh.device = cloned // update local copy of the device
3078 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3079
Gustavo Silva41af9122022-10-11 11:05:13 -03003080 if err := dh.cleanupDeviceResources(ctx); err != nil {
3081 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3082 } else {
3083 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3084 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003085
3086 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303087 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003088 if dh.isCollectorActive {
3089 dh.stopCollector <- true
3090 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303091 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003092 if dh.isHeartbeatCheckActive {
3093 dh.stopHeartbeatCheck <- true
3094 }
3095 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303096
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003097 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303098
Akash Kankanala041a2122024-10-16 15:49:22 +05303099 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303100 dh.adapterPreviouslyConnected = false
3101 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303102 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3103 if err != nil || childDevices == nil {
3104 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3105 continue
3106 }
3107 if len(childDevices.Items) == 0 {
3108 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3109 break
3110 } else {
3111 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3112 time.Sleep(5 * time.Second)
3113 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303114 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303115 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003116 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303117 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3118 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303119}
3120
balaji.nagarajan68f56e82025-07-04 15:16:01 +05303121// EnableOnuSerialNumber to enable onu serial number
3122func (dh *DeviceHandler) EnableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3123 logger.Debugw(ctx, "enable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3124 onuSerialNumber := device.SerialNumber
3125
3126 // fetch interfaceid from PortNo
3127 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3128
3129 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3130 if err != nil {
3131 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3132 log.Fields{
3133 "devicer-id": dh.device.Id,
3134 "serial-number": onuSerialNumber}, err).Log()
3135 }
3136
3137 onuIntf := &oop.InterfaceOnuSerialNumber{
3138 IntfId: ponID,
3139 OnuSerialNumber: sn,
3140 }
3141 _, err = dh.Client.EnableOnuSerialNumber(ctx, onuIntf)
3142
3143 if err != nil {
3144 logger.Errorw(ctx, "failed to enable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3145 return olterrors.NewErrAdapter("onu-serial-number-enable-failed", log.Fields{
3146 "device-id": dh.device.Id,
3147 "onu-serial-number": onuSerialNumber}, err)
3148 }
3149 return nil
3150}
3151
3152// DisableOnuSerialNumber to disable onu serial number
3153func (dh *DeviceHandler) DisableOnuSerialNumber(ctx context.Context, device *voltha.OnuSerialNumberOnOLTPon) error {
3154 logger.Debugw(ctx, "disable-onu-serial-number", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber, "port": device.Port.PortNo})
3155 onuSerialNumber := device.SerialNumber
3156 ponID := plt.PortNoToIntfID(device.Port.GetPortNo(), voltha.Port_PON_OLT)
3157 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3158 if err != nil {
3159 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3160 log.Fields{
3161 "devicer-id": dh.device.Id,
3162 "serial-number": onuSerialNumber}, err).Log()
3163 }
3164
3165 onuIntf := &oop.InterfaceOnuSerialNumber{
3166 OnuSerialNumber: sn,
3167 IntfId: ponID,
3168 }
3169 _, err = dh.Client.DisableOnuSerialNumber(ctx, onuIntf)
3170
3171 if err != nil {
3172 logger.Errorw(ctx, "failed to disable onu serial number", log.Fields{"onudev": onuSerialNumber, "error": err})
3173 return olterrors.NewErrAdapter("onu-serial-number-disable-failed", log.Fields{
3174 "device-id": dh.device.Id,
3175 "onu-serial-number": onuSerialNumber}, err)
3176 }
3177 return nil
3178}
3179
3180// EnableOnu to enable onu
3181func (dh *DeviceHandler) EnableOnu(ctx context.Context, device *voltha.Device) error {
3182 logger.Debugw(ctx, "enable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3183 onuSerialNumber := device.SerialNumber
3184 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3185 if InCacheOnuDev == nil {
3186 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3187 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3188 "device-id": dh.device.Id,
3189 "onu-serial-number": onuSerialNumber}, nil)
3190 }
3191 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})
3192
3193 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3194 if err != nil {
3195 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3196 log.Fields{
3197 "device-id": dh.device.Id,
3198 "serial-number": onuSerialNumber}, err).Log()
3199 }
3200
3201 onuIntf := &oop.InterfaceOnuSerialNumber{
3202 OnuSerialNumber: sn,
3203 IntfId: InCacheOnuDev.intfID,
3204 }
3205 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3206 OnuId: InCacheOnuDev.onuID,
3207 IntfIdSerialNum: onuIntf,
3208 }
3209 _, err = dh.Client.EnableOnu(ctx, onuIntfReq)
3210
3211 if err != nil {
3212 logger.Errorw(ctx, "failed to enable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3213 return olterrors.NewErrAdapter("onu-enable-failed", log.Fields{
3214 "olt-device-id": dh.device.Id,
3215 "onu-serial-number": onuSerialNumber}, err)
3216 }
3217 return nil
3218}
3219
3220// DisableOnu to disable onu
3221func (dh *DeviceHandler) DisableOnu(ctx context.Context, device *voltha.Device) error {
3222 logger.Debugw(ctx, "disable-onu", log.Fields{"Device": dh.device, "onu-serial-number": device.SerialNumber})
3223 onuSerialNumber := device.SerialNumber
3224 InCacheOnuDev := dh.getChildDevice(ctx, onuSerialNumber, dh.device.ParentPortNo)
3225 if InCacheOnuDev == nil {
3226 logger.Errorw(ctx, "failed to get child device from cache", log.Fields{"onudev": onuSerialNumber})
3227 return olterrors.NewErrAdapter("failed to get child device from cache", log.Fields{
3228 "device-id": dh.device.Id,
3229 "onu-serial-number": onuSerialNumber}, nil)
3230 }
3231 logger.Debugw(ctx, "successfully-received-child-device-from-cache", log.Fields{"child-device-intfid": InCacheOnuDev.intfID, "child-device-sn": InCacheOnuDev.serialNumber, "child-onuid": InCacheOnuDev.onuID})
3232
3233 sn, err := dh.deStringifySerialNumber(onuSerialNumber)
3234 if err != nil {
3235 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
3236 log.Fields{
3237 "device-id": dh.device.Id,
3238 "serial-number": onuSerialNumber}, err).Log()
3239 }
3240
3241 onuIntf := &oop.InterfaceOnuSerialNumber{
3242 OnuSerialNumber: sn,
3243 IntfId: InCacheOnuDev.intfID,
3244 }
3245 onuIntfReq := &oop.InterfaceOnuSerialNumberOnuId{
3246 OnuId: InCacheOnuDev.onuID,
3247 IntfIdSerialNum: onuIntf,
3248 }
3249 _, err = dh.Client.DisableOnu(ctx, onuIntfReq)
3250
3251 if err != nil {
3252 logger.Errorw(ctx, "failed to disable onu ", log.Fields{"onudev": onuSerialNumber, "error": err})
3253 return olterrors.NewErrAdapter("onu-disable-failed", log.Fields{
3254 "olt-device-id": dh.device.Id,
3255 "onu-serial-number": onuSerialNumber}, err)
3256 }
3257 return nil
3258}
3259
kesavand39e0aa32020-01-28 20:58:50 -05003260// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003261func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3262 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3263 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003264}
3265
3266// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003267func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3268 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3269 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003270}
3271
Mahir Gunyela2e68702022-12-07 00:00:42 -08003272// 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 +00003273func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3274 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003275 if port.GetType() == voltha.Port_ETHERNET_NNI {
3276 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003277 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303278 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303279 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003280 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003281 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003282 }
3283 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003284 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003285 ponIntf := &oop.Interface{IntfId: ponID}
3286 var operStatus voltha.OperStatus_Types
3287 if enablePort {
3288 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303289 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003290
3291 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303292 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003293 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003294 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003295 }
3296 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003297 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003298 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003299 } else {
3300 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303301 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003302 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303303 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003304 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003305 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003306 }
3307 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003308 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003309 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003310 }
khenaidoodc2116e2021-10-19 17:33:19 -04003311 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003312 DeviceId: dh.device.Id,
3313 PortType: voltha.Port_PON_OLT,
3314 PortNo: port.PortNo,
3315 OperStatus: operStatus,
3316 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303317 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303318 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003319 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003320 }
3321 return nil
3322}
3323
Mahir Gunyela2e68702022-12-07 00:00:42 -08003324// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003325func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003326 // Disable the port and update the oper_port_status to core
3327 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003328 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003329 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003330 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303331 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303332 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003333 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003334 }
3335 }
3336 }
3337 return nil
3338}
3339
Mahir Gunyela2e68702022-12-07 00:00:42 -08003340// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003341func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3342 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3343 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003344 if port.Type == voltha.Port_ETHERNET_NNI {
3345 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003346 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003347 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003348 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003349 }
3350 }
3351 if port.Type == voltha.Port_PON_OLT {
3352 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003353 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003354 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003355 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003356 }
3357 }
3358 }
3359}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003360
3361// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003362func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003363 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003364 if dh.getDeviceDeletionInProgressFlag() {
3365 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3366 // will reboot, so everything will be reset on the pOLT too.
3367 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3368 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3369 return nil
3370 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303371
3372 if dh.transitionMap.currentDeviceState != deviceStateUp {
3373 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})
3374 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3375 }
3376
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003377 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003378 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003379
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003380 var sn *oop.SerialNumber
3381 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003382 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303383 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003384 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303385 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003386 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003387 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003388
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003389 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303390 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003391 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003392 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3393 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3394 "device-id": dh.device.Id,
3395 "intf-id": intfID,
3396 "onuID": onuID,
3397 "err": err})
3398 } else {
3399 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003400 // Delete flows from device before schedulers and queue
3401 // Clear flowids for gem cache.
3402 removedFlows := []uint64{}
3403 for _, gem := range onuGem.GemPorts {
3404 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3405 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303406 // multiple gem port can have the same flow id
3407 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003408 var alreadyRemoved bool
3409 for _, removedFlowID := range removedFlows {
3410 if removedFlowID == flowID {
3411 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3412 alreadyRemoved = true
3413 break
3414 }
3415 }
3416 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003417 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003418 removedFlows = appendUnique64bit(removedFlows, flowID)
3419 }
3420 }
3421 }
3422 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3423 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003424 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3425 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3426 "device-id": dh.device.Id,
3427 "onu-device": onu,
3428 "err": err})
3429 }
yasin saplibddc2d72022-02-08 13:10:17 +00003430 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003431 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3432 "intf-id": intfID,
3433 "onu-device": onu,
3434 "onu-gem": onuGem,
3435 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303436 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003437 }
3438 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003439 }
yasin saplibddc2d72022-02-08 13:10:17 +00003440 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003441 dh.onus.Delete(onuKey)
3442 dh.discOnus.Delete(onuSn)
3443
3444 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003445 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303446 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303447 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003448 "onu-id": onuID}, err).Log()
3449 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003450
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003451 return nil
3452}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003453func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3454 flow := &oop.Flow{FlowId: flowID}
3455 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3456 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3457 "device-id": dh.device.Id})
3458 } else {
3459 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3460 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3461 "device-id": dh.device.Id,
3462 "err": err})
3463 }
3464 }
3465}
Girish Gowdracefae192020-03-19 18:14:10 -07003466
3467func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003468 for _, field := range flow_utils.GetOfbFields(flow) {
3469 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003470 return field.GetPort()
3471 }
3472 }
3473 return InvalidPort
3474}
3475
3476func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003477 for _, action := range flow_utils.GetActions(flow) {
3478 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003479 if out := action.GetOutput(); out != nil {
3480 return out.GetPort()
3481 }
3482 }
3483 }
3484 return InvalidPort
3485}
3486
Girish Gowdracefae192020-03-19 18:14:10 -07003487func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3488 inPort := getInPortFromFlow(flow)
3489 outPort := getOutPortFromFlow(flow)
3490
3491 if inPort == InvalidPort || outPort == InvalidPort {
3492 return inPort, outPort
3493 }
3494
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003495 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003496 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003497 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003498 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003499 return uniPort, outPort
3500 }
3501 }
3502 } else {
3503 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003504 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003505 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003506 return inPort, uniPort
3507 }
3508 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003509 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003510 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003511 return uniPort, outPort
3512 }
3513 }
3514 }
3515
3516 return InvalidPort, InvalidPort
3517}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003518
3519func extractOmciTransactionID(omciPkt []byte) uint16 {
3520 if len(omciPkt) > 3 {
3521 d := omciPkt[0:2]
3522 transid := binary.BigEndian.Uint16(d)
3523 return transid
3524 }
3525 return 0
3526}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003527
3528// StoreOnuDevice stores the onu parameters to the local cache.
3529func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3530 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3531 dh.onus.Store(onuKey, onuDevice)
3532}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003533
khenaidoodc2116e2021-10-19 17:33:19 -04003534func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003535 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003536 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003537 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003538 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003539 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003540 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003541 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003542 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3543 return nil, err
3544 }
3545 ID = device.ProxyAddress.GetOnuId()
3546 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3547 valueparam.Onu = &Onu
3548 valueparam.Value = value
3549
3550 // This API is unsupported until agent patch is added
3551 resp.Unsupported = uint32(value)
3552 _ = ctx
3553
3554 // Uncomment this code once agent changes are complete and tests
3555 /*
3556 resp, err = dh.Client.GetValue(ctx, valueparam)
3557 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003558 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003559 return nil, err
3560 }
3561 */
3562
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003563 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 -08003564 return resp, nil
3565}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003566
Akash Kankanala041a2122024-10-16 15:49:22 +05303567func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003568 // Default to NNI
3569 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003570 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003571 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003572 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003573 }
3574 return intfID
3575}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003576
Akash Kankanala041a2122024-10-16 15:49:22 +05303577func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003578 dh.perPonOnuIndicationChannelLock.Lock()
3579 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3580 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003581 return ch.indicationChannel
3582 }
3583 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303584 // We create a buffered channel here to avoid calling function to be blocked
3585 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003586 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003587 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003588 stopChannel: make(chan struct{}),
3589 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003590 dh.perPonOnuIndicationChannel[intfID] = channels
3591 dh.perPonOnuIndicationChannelLock.Unlock()
3592 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003593 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003594}
3595
Mahir Gunyelb0046752021-02-26 13:51:05 -08003596func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3597 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3598 dh.perPonOnuIndicationChannelLock.Lock()
3599 defer dh.perPonOnuIndicationChannelLock.Unlock()
3600 for _, v := range dh.perPonOnuIndicationChannel {
3601 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003602 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003603 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003604}
3605
Mahir Gunyelb0046752021-02-26 13:51:05 -08003606func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3607 ind := onuIndicationMsg{
3608 ctx: ctx,
3609 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003610 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003611 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003612 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303613 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003614}
3615
Mahir Gunyelb0046752021-02-26 13:51:05 -08003616func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003617 for {
3618 select {
3619 // process one indication per onu, before proceeding to the next one
3620 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003621 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003622 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003623 "ind": indication})
3624 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003625 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003626 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003627 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3628 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003629 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003630 }
3631 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003632 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003633 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3634 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003635 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003636 }
3637 }
3638 case <-onuChannels.stopChannel:
3639 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3640 close(onuChannels.indicationChannel)
3641 return
3642 }
3643 }
3644}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003645
3646// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3647// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003648func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003649 if dh.getDeviceDeletionInProgressFlag() {
3650 // The device itself is going to be reset as part of deletion. So nothing to be done.
3651 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3652 return nil
3653 }
3654
Girish Gowdra491a9c62021-01-06 16:43:07 -08003655 // Step1 : Fill McastFlowOrGroupControlBlock
3656 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3657 // Step3 : Wait on response channel for response
3658 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003659 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003660 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3661 errChan := make(chan error)
3662 var groupID uint32
3663 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3664 ctx: ctx,
3665 flowOrGroupAction: action,
3666 flow: flow,
3667 group: group,
3668 errChan: &errChan,
3669 }
3670 if flow != nil {
3671 groupID = flow_utils.GetGroup(flow)
3672 } else if group != nil {
3673 groupID = group.Desc.GroupId
3674 } else {
3675 return errors.New("flow-and-group-both-nil")
3676 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003677 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3678 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3679 // Derive the appropriate go routine to handle the request by a simple module operation.
3680 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3681 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3682 // Wait for handler to return error value
3683 err := <-errChan
3684 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3685 return err
3686 }
3687 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3688 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003689}
3690
3691// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003692func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003693 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003694 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003695 // block on the channel to receive an incoming mcast flow/group
3696 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003697 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3698 if mcastFlowOrGroupCb.flow != nil {
3699 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3700 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3701 log.Fields{"device-id": dh.device.Id,
3702 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003703 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3704 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3705 for _, flMgr := range dh.flowMgr {
3706 if flMgr != nil {
3707 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3708 break
3709 }
3710 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003711 // Pass the return value over the return channel
3712 *mcastFlowOrGroupCb.errChan <- err
3713 } else { // flow remove
3714 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3715 log.Fields{"device-id": dh.device.Id,
3716 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003717 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3718 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3719 for _, flMgr := range dh.flowMgr {
3720 if flMgr != nil {
3721 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3722 break
3723 }
3724 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003725 // Pass the return value over the return channel
3726 *mcastFlowOrGroupCb.errChan <- err
3727 }
3728 } else { // mcast group
mgouda86543582025-10-29 20:58:16 +05303729 switch mcastFlowOrGroupCb.flowOrGroupAction {
3730 case McastFlowOrGroupAdd:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003731 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3732 log.Fields{"device-id": dh.device.Id,
3733 "groupToAdd": mcastFlowOrGroupCb.group})
3734 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3735 // Pass the return value over the return channel
3736 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303737 case McastFlowOrGroupModify: // group modify
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003738 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3739 log.Fields{"device-id": dh.device.Id,
3740 "groupToModify": mcastFlowOrGroupCb.group})
3741 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3742 // Pass the return value over the return channel
3743 *mcastFlowOrGroupCb.errChan <- err
mgouda86543582025-10-29 20:58:16 +05303744 default: // group remove
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003745 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3746 log.Fields{"device-id": dh.device.Id,
3747 "groupToRemove": mcastFlowOrGroupCb.group})
3748 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3749 // Pass the return value over the return channel
3750 *mcastFlowOrGroupCb.errChan <- err
3751 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003752 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003753 case <-stopHandler:
3754 dh.mcastHandlerRoutineActive[routineIndex] = false
3755 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003756 }
3757 }
3758}
kesavand62126212021-01-12 04:56:06 -05003759
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003760// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003761func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003762 for i, v := range dh.stopMcastHandlerRoutine {
3763 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003764 select {
3765 case v <- true:
3766 case <-time.After(time.Second * 5):
3767 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3768 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003769 }
3770 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003771
3772 if dh.incomingMcastFlowOrGroup != nil {
3773 for k := range dh.incomingMcastFlowOrGroup {
3774 if dh.incomingMcastFlowOrGroup[k] != nil {
3775 dh.incomingMcastFlowOrGroup[k] = nil
3776 }
3777 }
3778 dh.incomingMcastFlowOrGroup = nil
3779 }
3780
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003781 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003782 logger.Debug(ctx, "stopped all mcast handler routines")
3783}
3784
Akash Kankanala041a2122024-10-16 15:49:22 +05303785// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003786func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003787 singleValResp := extension.SingleGetValueResponse{
3788 Response: &extension.GetValueResponse{
3789 Response: &extension.GetValueResponse_PortCoutners{
3790 PortCoutners: &extension.GetOltPortCountersResponse{},
3791 },
3792 },
3793 }
3794
Akash Kankanala041a2122024-10-16 15:49:22 +05303795 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003796 return &extension.SingleGetValueResponse{
3797 Response: &extension.GetValueResponse{
3798 Status: status,
3799 ErrReason: reason,
3800 },
3801 }
3802 }
3803
3804 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3805 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303806 // send error response
kesavand62126212021-01-12 04:56:06 -05003807 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3808 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3809 }
3810 statIndChn := make(chan bool, 1)
3811 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3812 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303813 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003814
3815 go func() {
3816 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3817 if err != nil {
3818 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3819 }
3820 }()
3821 select {
3822 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303823 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003824 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3825 case <-time.After(oltPortInfoTimeout * time.Second):
3826 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3827 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3828 case <-ctx.Done():
3829 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3830 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3831 }
mgouda86543582025-10-29 20:58:16 +05303832 switch oltPortInfo.PortType {
3833 case extension.GetOltPortCounters_Port_ETHERNET_NNI:
Akash Kankanala041a2122024-10-16 15:49:22 +05303834 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003835 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003836 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3837 cmnni := dh.portStats.collectNNIMetrics(intfID)
3838 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303839 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003840 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3841 }
3842 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3843 return &singleValResp
mgouda86543582025-10-29 20:58:16 +05303844 case extension.GetOltPortCounters_Port_PON_OLT:
kesavand62126212021-01-12 04:56:06 -05003845 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003846 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003847 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3848 cmpon := dh.portStats.collectPONMetrics(intfID)
3849 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303850 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003851 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3852 }
3853 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3854 return &singleValResp
3855 }
3856 }
3857 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3858}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303859
Akash Kankanala041a2122024-10-16 15:49:22 +05303860//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303861func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303862 singleValResp := extension.SingleGetValueResponse{
3863 Response: &extension.GetValueResponse{
3864 Status: extension.GetValueResponse_OK,
3865 Response: &extension.GetValueResponse_OffloadedAppsStats{
3866 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3867 },
3868 },
3869 }
3870
3871 return &singleValResp
3872}
3873
Akash Kankanala041a2122024-10-16 15:49:22 +05303874//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303875func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303876 singleValResp := extension.SingleSetValueResponse{
3877 Response: &extension.SetValueResponse{
3878 Status: extension.SetValueResponse_OK,
3879 },
3880 }
3881
3882 return &singleValResp
3883}
3884
Akash Kankanala041a2122024-10-16 15:49:22 +05303885//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303886func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303887 singleValResp := extension.SingleSetValueResponse{
3888 Response: &extension.SetValueResponse{
3889 Status: extension.SetValueResponse_OK,
3890 },
3891 }
3892
3893 return &singleValResp
3894}
3895
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303896func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303897 singleValResp := extension.SingleGetValueResponse{
3898 Response: &extension.GetValueResponse{
3899 Response: &extension.GetValueResponse_OnuPonCounters{
3900 OnuPonCounters: &extension.GetOnuCountersResponse{},
3901 },
3902 },
3903 }
3904
Akash Kankanala041a2122024-10-16 15:49:22 +05303905 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303906 return &extension.SingleGetValueResponse{
3907 Response: &extension.GetValueResponse{
3908 Status: status,
3909 ErrReason: reason,
3910 },
3911 }
3912 }
3913 intfID := onuPonInfo.IntfId
3914 onuID := onuPonInfo.OnuId
3915 onuKey := dh.formOnuKey(intfID, onuID)
3916
3917 if _, ok := dh.onus.Load(onuKey); !ok {
3918 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3919 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3920 }
3921 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3922 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3923 if cmnni == nil {
3924 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3925 }
3926 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3927 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303928}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003929
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303930func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3931 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3932 if err != nil {
3933 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3934 return nil, err
3935 }
3936 if onuGemInfo != nil {
3937 if len(onuGemInfo.UniPorts) == 0 {
3938 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3939 return nil, err
3940 }
3941 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3942 return onuGemInfo, nil
3943 }
3944 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3945 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3946}
3947
3948func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3949 var err error
3950 var allocStats *oop.OnuAllocIdStatistics
3951 var onuGemStats *oop.GemPortStatistics
3952 for _, uni := range onuGemInfo.UniPorts {
3953 uniID := plt.UniIDFromPortNum(uni)
3954 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3955 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3956 if len(tpIDs) == 0 {
3957 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3958 continue
3959 }
3960 for _, tpId := range tpIDs {
3961 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3962 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3963 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3964 if techProfileInstance != nil {
3965 switch tpInst := techProfileInstance.(type) {
3966 case *tp_pb.TechProfileInstance:
3967 allocId := tpInst.UsScheduler.AllocId
3968 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3969 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3970 if err != nil {
3971 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3972 return err
3973 }
3974 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3975 allocIdInfo.AllocId = allocStats.AllocId
3976 allocIdInfo.RxBytes = allocStats.RxBytes
3977
3978 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3979
3980 gemPorts := tpInst.UpstreamGemPortAttributeList
3981 for _, gem := range gemPorts {
3982 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3983 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
3984 if err != nil {
3985 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
3986 return err
3987 }
3988 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
3989 gemStatsInfo.GemId = onuGemStats.GemportId
3990 gemStatsInfo.RxBytes = onuGemStats.RxBytes
3991 gemStatsInfo.RxPackets = onuGemStats.RxPackets
3992 gemStatsInfo.TxBytes = onuGemStats.TxBytes
3993 gemStatsInfo.TxPackets = onuGemStats.TxPackets
3994
3995 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
3996 }
3997 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
3998
3999 default:
4000 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
4001 return err
4002 }
4003 } else {
4004 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
4005 continue
4006 }
4007 }
4008 }
4009 return err
4010}
4011
4012//nolint:unparam
4013func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
4014 singleValResp := extension.SingleGetValueResponse{
4015 Response: &extension.GetValueResponse{
4016 Status: extension.GetValueResponse_OK,
4017 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
4018 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
4019 },
4020 },
4021 }
4022 errResp := func(status extension.GetValueResponse_Status,
4023 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4024 return &extension.SingleGetValueResponse{
4025 Response: &extension.GetValueResponse{
4026 Status: status,
4027 ErrReason: reason,
4028 },
4029 }
4030 }
4031
4032 var intfID, onuID uint32
4033 if onuDevice != nil {
4034 onuID = onuDevice.ProxyAddress.OnuId
4035 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
4036 }
4037
4038 onuKey := dh.formOnuKey(intfID, onuID)
4039 if _, ok := dh.onus.Load(onuKey); !ok {
4040 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
4041 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4042 }
4043 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
4044
4045 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
4046 if err == nil {
4047 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
4048 if err != nil {
4049 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4050 }
4051 } else {
4052 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4053 }
4054 return &singleValResp
4055}
4056
nikesh.krishnanc8473432023-06-14 12:14:54 +05304057func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304058 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
4059 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
4060 if err != nil {
4061 return nil, err
4062 }
4063 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304064}
4065
4066func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05304067 Intf := oop.Interface{IntfId: intfID}
4068 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
4069 if err != nil {
4070 return nil, err
4071 }
4072 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05304073}
4074
Gamze Abaka85e9a142021-05-26 13:41:39 +00004075func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004076 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
4077 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4078 if err != nil {
4079 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4080 return generateSingleGetValueErrorResponse(err)
4081 }
4082 return &extension.SingleGetValueResponse{
4083 Response: &extension.GetValueResponse{
4084 Status: extension.GetValueResponse_OK,
4085 Response: &extension.GetValueResponse_RxPower{
4086 RxPower: &extension.GetRxPowerResponse{
4087 IntfId: rxPowerRequest.IntfId,
4088 OnuId: rxPowerRequest.OnuId,
4089 Status: rxPower.Status,
4090 FailReason: rxPower.FailReason.String(),
4091 RxPower: rxPower.RxPowerMeanDbm,
4092 },
4093 },
4094 },
4095 }
4096}
4097
praneeth nalmas55616d62023-02-06 09:19:18 +05304098func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304099 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05304100 return &extension.SingleGetValueResponse{
4101 Response: &extension.GetValueResponse{
4102 Status: status,
4103 ErrReason: reason,
4104 },
4105 }
4106 }
4107
4108 resp := extension.SingleGetValueResponse{
4109 Response: &extension.GetValueResponse{
4110 Status: extension.GetValueResponse_OK,
4111 Response: &extension.GetValueResponse_OltRxPower{
4112 OltRxPower: &extension.GetOltRxPowerResponse{},
4113 },
4114 },
4115 }
4116
4117 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
4118 portLabel := OltRxPowerRequest.PortLabel
4119 serialNumber := OltRxPowerRequest.OnuSn
4120
4121 portInfo := strings.Split(portLabel, "-")
4122 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4123
4124 if err != nil {
4125 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4126 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4127 }
4128
4129 if portInfo[0] != "pon" {
4130 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
4131 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4132 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304133
4134 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05304135 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
4136 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304137 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
4138 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4139 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05304140 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
4141 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05304142 }
4143
4144 rxPowerValue := extension.RxPower{}
4145 rxPowerValue.OnuSn = onuDev.serialNumber
4146 rxPowerValue.Status = rxPower.GetStatus()
4147 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4148 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4149
4150 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05304151 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304152 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
4153 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4154 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304155 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304156 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304157 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05304158 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05304159 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
4160 if err != nil {
4161 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
4162 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05304163 rxPowerValue := extension.RxPower{}
4164 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
4165 rxPowerValue.Status = rxPower.GetStatus()
4166 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
4167 rxPowerValue.FailReason = rxPower.GetFailReason().String()
4168
4169 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
4170 }
praneeth nalmas55616d62023-02-06 09:19:18 +05304171 }
4172 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4173 return true
4174 })
4175 }
4176 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
4177 return &resp
4178}
4179
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05304180func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
4181 errResp := func(status extension.GetValueResponse_Status,
4182 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4183 return &extension.SingleGetValueResponse{
4184 Response: &extension.GetValueResponse{
4185 Status: status,
4186 ErrReason: reason,
4187 },
4188 }
4189 }
4190
4191 resp := extension.SingleGetValueResponse{
4192 Response: &extension.GetValueResponse{
4193 Status: extension.GetValueResponse_OK,
4194 Response: &extension.GetValueResponse_OltPonStatsResponse{
4195 OltPonStatsResponse: &extension.GetPonStatsResponse{},
4196 },
4197 },
4198 }
4199
4200 portLabel := ponStatsRequest.GetPortLabel()
4201 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4202
4203 portInfo := strings.Split(portLabel, "-")
4204 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4205
4206 if err != nil {
4207 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4208 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4209 }
4210
4211 if portInfo[0] != "pon" {
4212 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4213 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4214 }
4215
4216 Interface := oop.Interface{IntfId: uint32(portNumber)}
4217 ponStats, err := dh.Client.GetPonPortStatistics(ctx, &Interface)
4218 if err != nil {
4219 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
4220 return generateSingleGetValueErrorResponse(err)
4221 }
4222
4223 ponPortStats := resp.Response.GetOltPonStatsResponse()
4224 ponPortStats.PonPort = uint32(portNumber)
4225 ponPortStats.PortStatistics = ponStats
4226
4227 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4228 return &resp
4229}
4230
4231func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4232 errResp := func(status extension.GetValueResponse_Status,
4233 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4234 return &extension.SingleGetValueResponse{
4235 Response: &extension.GetValueResponse{
4236 Status: status,
4237 ErrReason: reason,
4238 },
4239 }
4240 }
4241
4242 resp := extension.SingleGetValueResponse{
4243 Response: &extension.GetValueResponse{
4244 Status: extension.GetValueResponse_OK,
4245 Response: &extension.GetValueResponse_OltNniStatsResponse{
4246 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4247 },
4248 },
4249 }
4250
4251 portLabel := nniStatsRequest.GetPortLabel()
4252 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4253
4254 portInfo := strings.Split(portLabel, "-")
4255 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4256
4257 if err != nil {
4258 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4259 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4260 }
4261
4262 if portInfo[0] != "nni" {
4263 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4264 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4265 }
4266
4267 Interface := oop.Interface{IntfId: uint32(portNumber)}
4268 nniStats, err := dh.Client.GetNniPortStatistics(ctx, &Interface)
4269 if err != nil {
4270 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4271 return generateSingleGetValueErrorResponse(err)
4272 }
4273
4274 nniPortStats := resp.Response.GetOltNniStatsResponse()
4275 nniPortStats.NniPort = uint32(portNumber)
4276 nniPortStats.PortStatistics = nniStats
4277
4278 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4279 return &resp
4280}
4281
Akash Kankanala041a2122024-10-16 15:49:22 +05304282// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004283func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304284 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004285 return &extension.SingleGetValueResponse{
4286 Response: &extension.GetValueResponse{
4287 Status: status,
4288 ErrReason: reason,
4289 },
4290 }
4291 }
4292
4293 if err != nil {
4294 if e, ok := status.FromError(err); ok {
4295 switch e.Code() {
4296 case codes.Internal:
4297 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4298 case codes.DeadlineExceeded:
4299 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4300 case codes.Unimplemented:
4301 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4302 case codes.NotFound:
4303 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4304 }
4305 }
4306 }
4307
4308 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4309}
khenaidoo106c61a2021-08-11 18:05:46 -04004310
4311/*
4312Helper functions to communicate with Core
4313*/
4314
4315func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4316 cClient, err := dh.coreClient.GetCoreServiceClient()
4317 if err != nil || cClient == nil {
4318 return nil, err
4319 }
4320 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4321 defer cancel()
4322 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4323}
4324
khenaidoodc2116e2021-10-19 17:33:19 -04004325func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004326 cClient, err := dh.coreClient.GetCoreServiceClient()
4327 if err != nil || cClient == nil {
4328 return nil, err
4329 }
4330 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4331 defer cancel()
4332 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4333}
4334
khenaidoodc2116e2021-10-19 17:33:19 -04004335func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004336 cClient, err := dh.coreClient.GetCoreServiceClient()
4337 if err != nil || cClient == nil {
4338 return err
4339 }
4340 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4341 defer cancel()
4342 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4343 return err
4344}
4345
4346func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4347 cClient, err := dh.coreClient.GetCoreServiceClient()
4348 if err != nil || cClient == nil {
4349 return nil, err
4350 }
4351 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4352 defer cancel()
4353 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4354}
4355
4356func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4357 cClient, err := dh.coreClient.GetCoreServiceClient()
4358 if err != nil || cClient == nil {
4359 return nil, err
4360 }
4361 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4362 defer cancel()
4363 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4364}
4365
4366func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4367 cClient, err := dh.coreClient.GetCoreServiceClient()
4368 if err != nil || cClient == nil {
4369 return err
4370 }
4371 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4372 defer cancel()
4373 _, err = cClient.DeviceUpdate(subCtx, device)
4374 return err
4375}
4376
khenaidoodc2116e2021-10-19 17:33:19 -04004377func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004378 cClient, err := dh.coreClient.GetCoreServiceClient()
4379 if err != nil || cClient == nil {
4380 return nil, err
4381 }
4382 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4383 defer cancel()
4384 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4385}
4386
khenaidoodc2116e2021-10-19 17:33:19 -04004387func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004388 cClient, err := dh.coreClient.GetCoreServiceClient()
4389 if err != nil || cClient == nil {
4390 return err
4391 }
4392 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4393 defer cancel()
4394 _, err = cClient.SendPacketIn(subCtx, pkt)
4395 return err
4396}
4397
4398func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4399 cClient, err := dh.coreClient.GetCoreServiceClient()
4400 if err != nil || cClient == nil {
4401 return err
4402 }
4403 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4404 defer cancel()
4405 _, err = cClient.PortCreated(subCtx, port)
4406 return err
4407}
4408
khenaidoodc2116e2021-10-19 17:33:19 -04004409func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004410 cClient, err := dh.coreClient.GetCoreServiceClient()
4411 if err != nil || cClient == nil {
4412 return err
4413 }
4414 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4415 defer cancel()
4416 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4417 return err
4418}
4419
khenaidoodc2116e2021-10-19 17:33:19 -04004420func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004421 cClient, err := dh.coreClient.GetCoreServiceClient()
4422 if err != nil || cClient == nil {
4423 return err
4424 }
4425 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4426 defer cancel()
4427 _, err = cClient.PortStateUpdate(subCtx, portState)
4428 return err
4429}
4430
khenaidoodc2116e2021-10-19 17:33:19 -04004431func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004432 cClient, err := dh.coreClient.GetCoreServiceClient()
4433 if err != nil || cClient == nil {
4434 return nil, err
4435 }
4436 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4437 defer cancel()
4438 return cClient.GetDevicePort(subCtx, portFilter)
4439}
4440
nikesh.krishnanc8473432023-06-14 12:14:54 +05304441func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4442 cClient, err := dh.coreClient.GetCoreServiceClient()
4443 if err != nil || cClient == nil {
4444 return nil, err
4445 }
4446 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4447 defer cancel()
4448 return cClient.GetPorts(subCtx, portFilter)
4449}
4450
khenaidoo106c61a2021-08-11 18:05:46 -04004451/*
4452Helper functions to communicate with child adapter
4453*/
4454
khenaidoodc2116e2021-10-19 17:33:19 -04004455func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004456 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4457 if err != nil || aClient == nil {
4458 return err
4459 }
4460 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4461 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4462 defer cancel()
4463 _, err = aClient.OmciIndication(subCtx, response)
4464 return err
4465}
4466
khenaidoodc2116e2021-10-19 17:33:19 -04004467func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004468 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4469 if err != nil || aClient == nil {
4470 return err
4471 }
4472 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4473 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4474 defer cancel()
4475 _, err = aClient.OnuIndication(subCtx, onuInd)
4476 return err
4477}
4478
khenaidoodc2116e2021-10-19 17:33:19 -04004479func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004480 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4481 if err != nil || aClient == nil {
4482 return err
4483 }
4484 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4485 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4486 defer cancel()
4487 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4488 return err
4489}
4490
khenaidoodc2116e2021-10-19 17:33:19 -04004491func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004492 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4493 if err != nil || aClient == nil {
4494 return err
4495 }
4496 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4497 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4498 defer cancel()
4499 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4500 return err
4501}
4502
khenaidoodc2116e2021-10-19 17:33:19 -04004503func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004504 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4505 if err != nil || aClient == nil {
4506 return err
4507 }
4508 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4509 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4510 defer cancel()
4511 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4512 return err
4513}
4514
4515/*
4516Helper functions for remote communication
4517*/
4518
4519// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4520// supports is deleted
4521func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4522 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4523
4524 dh.lockChildAdapterClients.Lock()
4525 defer dh.lockChildAdapterClients.Unlock()
4526 if _, ok := dh.childAdapterClients[endpoint]; ok {
4527 // Already set
4528 return nil
4529 }
4530
4531 // Setup child's adapter grpc connection
4532 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004533 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4534 dh.cfg.AdapterEndpoint,
4535 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004536 "onu_inter_adapter_service.OnuInterAdapterService",
4537 dh.onuInterAdapterRestarted,
4538 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004539 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4540 return err
4541 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304542 retryCodes := []codes.Code{
4543 codes.Unavailable, // server is currently unavailable
4544 codes.DeadlineExceeded, // deadline for the operation was exceeded
4545 }
4546 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4547 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 -04004548
nikesh.krishnand9812542023-08-01 18:31:39 +05304549 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004550 // Wait until we have a connection to the child adapter.
4551 // Unlimited retries or until context expires
4552 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4553 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4554 for {
4555 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4556 if err == nil && client != nil {
4557 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4558 break
4559 }
4560 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4561 // Backoff
4562 if err = backoff.Backoff(subCtx); err != nil {
4563 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4564 break
4565 }
4566 }
4567 return nil
4568}
4569
khenaidoodc2116e2021-10-19 17:33:19 -04004570func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004571 // First check from cache
4572 dh.lockChildAdapterClients.RLock()
4573 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4574 dh.lockChildAdapterClients.RUnlock()
4575 return cgClient.GetOnuInterAdapterServiceClient()
4576 }
4577 dh.lockChildAdapterClients.RUnlock()
4578
4579 // Set the child connection - can occur on restarts
4580 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4581 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4582 cancel()
4583 if err != nil {
4584 return nil, err
4585 }
4586
4587 // Get the child client now
4588 dh.lockChildAdapterClients.RLock()
4589 defer dh.lockChildAdapterClients.RUnlock()
4590 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4591 return cgClient.GetOnuInterAdapterServiceClient()
4592 }
4593 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4594}
4595
4596func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4597 dh.lockChildAdapterClients.Lock()
4598 defer dh.lockChildAdapterClients.Unlock()
4599 for key, client := range dh.childAdapterClients {
4600 client.Stop(ctx)
4601 delete(dh.childAdapterClients, key)
4602 }
4603}
4604
khenaidooefff76e2021-12-15 16:51:30 -05004605// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4606func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4607 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004608 return nil
4609}
4610
khenaidooefff76e2021-12-15 16:51:30 -05004611// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4612func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4613 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004614 return nil
4615 }
khenaidooefff76e2021-12-15 16:51:30 -05004616 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004617}
Girish Gowdra950326e2021-11-05 12:43:24 -07004618
4619func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4620 dh.lockDevice.Lock()
4621 defer dh.lockDevice.Unlock()
4622 dh.isDeviceDeletionInProgress = flag
4623}
4624
4625func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4626 dh.lockDevice.RLock()
4627 defer dh.lockDevice.RUnlock()
4628 return dh.isDeviceDeletionInProgress
4629}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004630
4631// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4632// Returns false if waiting timed out.
4633func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4634 c := make(chan struct{})
4635 go func() {
4636 defer close(c)
4637 wg.Wait()
4638 }()
4639 select {
4640 case <-c:
4641 return true // completed normally
4642 case <-time.After(timeout):
4643 return false // timed out
4644 }
4645}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304646
4647func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4648 val, err := json.Marshal(signature)
4649 if err != nil {
4650 logger.Error(ctx, "failed-to-marshal")
4651 return
4652 }
4653 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4654 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4655 }
4656}
4657
4658func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4659 var signature uint32
4660
4661 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4662 if er == nil {
4663 if Value != nil {
4664 Val, er := kvstore.ToByte(Value.Value)
4665 if er != nil {
4666 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4667 return signature
4668 }
4669 if er = json.Unmarshal(Val, &signature); er != nil {
4670 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4671 return signature
4672 }
4673 }
4674 }
4675 return signature
4676}