blob: c866695aa8ab95cccecdb5f40b49ec31a69cd8e8 [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",
180 "rx_mcast_packets",
181 "rx_bcast_packets",
182 "tx_bytes",
183 "tx_packets",
184 "tx_mcast_packets",
185 "tx_bcast_packets",
186}
187
Mahir Gunyela2e68702022-12-07 00:00:42 -0800188// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400189func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700190 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700191 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700192 device.deviceType = deviceTp
193 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700194 device.onuID = onuID
195 device.intfID = intfID
196 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530197 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400198 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700199 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530200}
201
Mahir Gunyela2e68702022-12-07 00:00:42 -0800202// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400203func 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 -0700204 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530205 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800206 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400207 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400208 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700209 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700210 dh.device = cloned
211 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500212 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700213 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000214 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
215 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530216 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 -0500217 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800218 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800219 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400220 dh.childAdapterClients = make(map[string]*vgrpc.Client)
221 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300222 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530223 if dh.kvStore == nil {
224 logger.Error(ctx, "Failed to setup KV store")
225 return nil
226 }
227
Girish Gowdra491a9c62021-01-06 16:43:07 -0800228 // Create a slice of buffered channels for handling concurrent mcast flow/group.
229 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700230 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
231 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800232 for i := range dh.incomingMcastFlowOrGroup {
233 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800234 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800235 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
236 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
237 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
238 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700239 dh.mcastHandlerRoutineActive[i] = true
240 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800241 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530242 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700243 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530244}
245
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530246func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
247 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
248 switch storeType {
249 case "etcd":
250 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530251 case "redis":
252 return kvstore.NewRedisClient(address, timeout, false)
253 case "redis-sentinel":
254 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530255 }
256 return nil, errors.New("unsupported-kv-store")
257}
258
259// SetKVClient sets the KV client and return a kv backend
260func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
261 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
262 if err != nil {
263 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
264 return nil
265 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530266 kvbackend := &db.Backend{
267 Client: kvClient,
268 StoreType: backend,
269 Address: addr,
270 Timeout: rsrcMgr.KvstoreTimeout,
271 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
272
273 return kvbackend
274}
275
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000276// CloseKVClient closes open KV clients
277func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
278 if dh.resourceMgr != nil {
279 for _, rscMgr := range dh.resourceMgr {
280 if rscMgr != nil {
281 rscMgr.CloseKVClient(ctx)
282 }
283 }
284 }
285 if dh.flowMgr != nil {
286 for _, flMgr := range dh.flowMgr {
287 if flMgr != nil {
288 flMgr.CloseKVClient(ctx)
289 }
290 }
291 }
292}
293
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530294// start save the device to the data model
295func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700296 dh.lockDevice.Lock()
297 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000298 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700299 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000300 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530301}
302
khenaidooefff76e2021-12-15 16:51:30 -0500303// Stop stops the device handler
304func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700305 dh.lockDevice.Lock()
306 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000307 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500308 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400309
khenaidooefff76e2021-12-15 16:51:30 -0500310 // Delete (which will stop also) all grpc connections to the child adapters
311 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530313}
314
ssiddiqui04386ee2021-08-23 21:58:25 +0530315func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
316 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
317 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
318 if pooledIntfID == intfID {
319 return resourceRanges.GetTechnology()
320 }
321 }
322 }
323 return ""
324}
325
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400326func macifyIP(ip net.IP) string {
327 if len(ip) > 0 {
328 oct1 := strconv.FormatInt(int64(ip[12]), 16)
329 oct2 := strconv.FormatInt(int64(ip[13]), 16)
330 oct3 := strconv.FormatInt(int64(ip[14]), 16)
331 oct4 := strconv.FormatInt(int64(ip[15]), 16)
332 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
333 }
334 return ""
335}
336
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400338 var genmac string
339 var addr net.IP
340 var ips []string
341 var err error
342
Neha Sharma96b7bf22020-06-15 10:37:32 +0000343 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400344
345 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000346 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400347
348 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000349 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400350 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000351 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400352 }
353 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530355 log.Fields{"host": ips[0],
356 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400357 return genmac, nil
358 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000359 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400360 }
361
362 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000363 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530364 log.Fields{"host": host,
365 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400366 return genmac, nil
367}
368
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530369func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700370 slist := strings.Split(mac, ":")
371 result := make([]uint32, len(slist))
372 var err error
373 var tmp int64
374 for index, val := range slist {
375 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
376 return []uint32{1, 2, 3, 4, 5, 6}
377 }
378 result[index] = uint32(tmp)
379 }
380 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530381}
382
Mahir Gunyela2e68702022-12-07 00:00:42 -0800383// 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 -0800384func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800385 switch portType {
386 case voltha.Port_ETHERNET_NNI:
387 return fmt.Sprintf("nni-%d", portNum), nil
388 case voltha.Port_PON_OLT:
389 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700390 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800391
Girish Kumarf26e4882020-03-05 06:49:10 +0000392 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530393}
394
Elia Battiston596406d2022-02-02 12:19:00 +0100395func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
396 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530397 // In case it was not set in the indication
398 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100399 speedMbps = defaultPortSpeedMbps
400 }
401
402 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
403 switch speedMbps {
404 case 1000000:
405 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
406 case 100000:
407 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
408 case 40000:
409 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
410 case 10000:
411 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
412 case 1000:
413 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
414 case 100:
415 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
416 case 10:
417 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
418 }
419
420 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
421
422 port := &of.OfpPort{
423 HwAddr: macAddressToUint32Array(macAddress),
424 Config: 0,
425 State: uint32(of.OfpPortState_OFPPS_LIVE),
426 Curr: capacity,
427 Advertised: capacity,
428 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530429 CurrSpeed: speedMbps * 1000, // kbps
430 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100431 }
432
433 return port
434}
435
436func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000437 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700438 if state == "up" {
439 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530440 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500441 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700442 } else {
443 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500444 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700445 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700446 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400447 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800448 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000449 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400450 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500451
khenaidoo106c61a2021-08-11 18:05:46 -0400452 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400453 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400454 DeviceId: dh.device.Id,
455 Port: portNum,
456 })
457 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000458 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400459 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400460 DeviceId: dh.device.Id,
461 PortType: portType,
462 PortNo: portNum,
463 OperStatus: operStatus})
464 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400465 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
466 "device-id": dh.device.Id,
467 "port-type": portType,
468 "port-number": portNum,
469 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500470 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400471 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500472 }
khenaidoo106c61a2021-08-11 18:05:46 -0400473
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400474 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400475 port = &voltha.Port{
476 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700477 PortNo: portNum,
478 Label: label,
479 Type: portType,
480 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100481 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700482 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000483 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400485 err = dh.createPortInCore(ctx, port)
486 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000487 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800488 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000489 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400490 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000491 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530492 return nil
493}
494
Kent Hagermane6ff1012020-07-14 15:07:53 -0400495func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400496 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530497 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400498 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
499 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530500 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800501 dh.lockDevice.Lock()
502 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530503 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530504}
505
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700506// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530507// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800508func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000509 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700510 defer func() {
511 dh.lockDevice.Lock()
512 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530513 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700514 dh.lockDevice.Unlock()
515 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700516 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700517 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700518 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700519 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400520
David Bainbridgef5879ca2019-12-13 21:17:54 +0000521 // Create an exponential backoff around re-enabling indications. The
522 // maximum elapsed time for the back off is set to 0 so that we will
523 // continue to retry. The max interval defaults to 1m, but is set
524 // here for code clarity
525 indicationBackoff := backoff.NewExponentialBackOff()
526 indicationBackoff.MaxElapsedTime = 0
527 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700528
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700529 dh.lockDevice.Lock()
530 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530531 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700532 dh.lockDevice.Unlock()
533
Girish Gowdra3f974912020-03-23 20:35:18 -0700534Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700535 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400536 select {
537 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000538 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700539 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400540 default:
541 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100542
543 select {
544 case <-indications.Context().Done():
545 if err != nil {
546 logger.Warnw(ctx, "error-during-enable-indications",
547 log.Fields{"err": err,
548 "device-id": dh.device.Id})
549 }
550
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400551 // Use an exponential back off to prevent getting into a tight loop
552 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100553 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
554 "device-id": dh.device.Id,
555 "duration": duration,
556 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400557 if duration == backoff.Stop {
558 // If we reach a maximum then warn and reset the backoff
559 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100560 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530561 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530562 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400563 indicationBackoff.Reset()
564 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700565
566 // On failure process a backoff timer while watching for stopIndications
567 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700568 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700569 select {
570 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000571 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700572 if !backoffTimer.Stop() {
573 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700574 }
575 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700576 case <-backoffTimer.C:
577 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700578 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700579 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
580 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400581 }
582 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100583 default:
584 if err != nil {
585 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530586 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530587 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100588 // Close the stream, and re-initialize it
589 if err = indications.CloseSend(); err != nil {
590 // Ok to ignore here, because we landed here due to a problem on the stream
591 // In all probability, the closeSend call may fail
592 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
593 log.Fields{"err": err,
594 "device-id": dh.device.Id})
595 }
596 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
597 return err
598 }
599 // once we re-initialized the indication stream, continue to read indications
600 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700601 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100602 // Reset backoff if we have a successful receive
603 indicationBackoff.Reset()
604 // When OLT is admin down, ignore all indications.
605 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
606 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
607 log.Fields{"indication": indication,
608 "device-id": dh.device.Id})
609 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700610 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100611 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530612 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700613 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700615 // Close the send stream
616 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700617
Girish Gowdra3f974912020-03-23 20:35:18 -0700618 return nil
619}
620
621func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700622 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700623 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
624 if err != nil {
625 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
626 }
627 if indications == nil {
628 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
629 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700630 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700631 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400632}
633
634// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
635func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
636 switch indication.Data.(type) {
637 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
638 return true
639
640 default:
641 return false
642 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643}
644
David K. Bainbridge794735f2020-02-11 21:01:37 -0800645func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700646 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000647 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530648 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530650 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000652 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000653 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530654 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000655 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800656 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000657 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800658 }
659 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700660}
661
Akash Kankanala041a2122024-10-16 15:49:22 +0530662// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530663func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700664 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 switch indication.Data.(type) {
666 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000667 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
668 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700669 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 -0800670 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400671 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800672 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000674 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
675 defer span.Finish()
676
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800678 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100679 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400680 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800681 }
682 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000683 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700684 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000685 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
686 defer span.Finish()
687
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700688 intfOperInd := indication.GetIntfOperInd()
689 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100691 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400692 _ = 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 -0800693 }
694 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 } else if intfOperInd.GetType() == "pon" {
696 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
697 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800698 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100699 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400700 _ = 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 -0800701 }
702 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700704 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000705 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530706 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530707 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000709 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
710 defer span.Finish()
711
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700712 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000713 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530714 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800715 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700716 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000717 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
718 defer span.Finish()
719
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700720 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530722 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800723 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000725 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
726 defer span.Finish()
727
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000729 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 -0800730 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000731 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400732 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800733 }
734 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000736 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
737 defer span.Finish()
738
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000740 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700741 "intf-type": pktInd.IntfId,
742 "intf-id": pktInd.IntfId,
743 "gem-port-id": pktInd.GemportId,
744 "port-no": pktInd.PortNo,
745 "device-id": dh.device.Id,
746 })
747
748 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000749 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700750 "intf-type": pktInd.IntfId,
751 "intf-id": pktInd.IntfId,
752 "gem-port-id": pktInd.GemportId,
753 "port-no": pktInd.PortNo,
754 "packet": hex.EncodeToString(pktInd.Pkt),
755 "device-id": dh.device.Id,
756 })
757 }
758
David K. Bainbridge794735f2020-02-11 21:01:37 -0800759 go func() {
760 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400761 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800762 }
763 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000765 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
766 defer span.Finish()
767
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700769 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000771 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
772 defer span.Finish()
773
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000775 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000777 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
778 defer span.Finish()
779
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700780 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000781 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
782 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700783 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530784}
785
nikesh.krishnanc8473432023-06-14 12:14:54 +0530786func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
787 onuInd := &oop.OnuIndication{
788 IntfId: intfID,
789 OnuId: onuID,
790 OperState: operState,
791 AdminState: adminState,
792 }
793 indication := &oop.Indication{
794 Data: &oop.Indication_OnuInd{
795 OnuInd: onuInd,
796 },
797 }
798 return indication
799}
800
801func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
802 onuAlarmInd := &oop.OnuAlarmIndication{
803 IntfId: intfID,
804 OnuId: onuID,
805 LosStatus: losStatus,
806 }
807 alarmInd := &oop.AlarmIndication{
808 Data: &oop.AlarmIndication_OnuAlarmInd{
809 OnuAlarmInd: onuAlarmInd,
810 },
811 }
812 return alarmInd
813}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530814
Akash Kankanala041a2122024-10-16 15:49:22 +0530815func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530816 ponlosAlarmInd := &oop.LosIndication{
817 IntfId: intfID,
818 Status: losStatus,
819 }
820 alarmInd := &oop.AlarmIndication{
821 Data: &oop.AlarmIndication_LosInd{
822 LosInd: ponlosAlarmInd,
823 },
824 }
825 return alarmInd
826}
Akash Kankanala041a2122024-10-16 15:49:22 +0530827
nikesh.krishnanc8473432023-06-14 12:14:54 +0530828func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
829 go func() {
830 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
831 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
832 }
833 }()
834
835 raisedTs := time.Now().Unix()
836 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
837}
838
839func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530840 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
841 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530842 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530843 return err
844 }
845 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530846 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
847 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
848 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
849
850 onuID := onuDeviceFromCore.ProxyAddress.OnuId
851 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
852 if err != nil {
853 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530854 } else {
855 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
856 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
857 switch {
858 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
859 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
860 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
861
862 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530863 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530864 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
865 raisedTs := time.Now().Unix()
866 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
867
868 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
869 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530870 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530871 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530872 return nil
873}
874
875func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
876 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
877 DeviceId: dh.device.Id,
878 PortType: voltha.Port_PON_OLT,
879 })
880 if err != nil {
881 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530882 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530883 }
884 for _, portFromCore := range portsFromCore.Items {
885 portNum := portFromCore.GetPortNo()
886 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
887 portOperStatusFromCore := portFromCore.OperStatus
888 portAdminStateFromCore := portFromCore.AdminState
889 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
890 if err != nil {
891 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
892 } else {
893 portLosFromOlt := ponPortFromOlt.GetLos()
894 portStateFromOlt := ponPortFromOlt.GetState()
895 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
896 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
897 "portStateFromOlt": portStateFromOlt.String(),
898 "portOperStatusFromCore": portOperStatusFromCore.String(),
899 "device-id": dh.device.Id,
900 "port": portNum})
901 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
902 raisedTs := time.Now().Unix()
903 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530904 }
905 switch {
906 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
907 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
908 "portStateFromOlt": portStateFromOlt.String(),
909 "portOperStatusFromCore": portOperStatusFromCore.String(),
910 "device-id": dh.device.Id,
911 "port": portNum})
912 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
913 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
914 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
915 "portStateFromOlt": portStateFromOlt.String(),
916 "portOperStatusFromCore": portOperStatusFromCore.String(),
917 "device-id": dh.device.Id,
918 "port": portNum})
919 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
920 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
921 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
922 "device-id": dh.device.Id,
923 "port": portNum})
924 default:
925 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
926 "portStateFromOlt": portStateFromOlt.String(),
927 "portOperStatusFromCore": portOperStatusFromCore.String(),
928 "device-id": dh.device.Id,
929 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530930 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530931 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530932 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530933 return nil
934}
935
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530936// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530937func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530938 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +0530939 // Declare deviceStateFilter to be used later
940 var deviceStateFilter *ca.DeviceStateFilter
bseenivaaa9165b2025-09-18 17:28:12 +0530941 dh.collectorWaitGroup.Add(1)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530943 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530944 if err != nil {
945 return fmt.Errorf("failed to get device from core: %w", err)
946 }
947 logger.Info(ctx, "Device state", log.Fields{
948 "device-id": device.Id,
949 "CurrOperStatus": device.OperStatus,
950 "CurrConnStatus": device.ConnectStatus,
951 })
952 // Perform cleanup if the device's operational status is REBOOTED
953 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
954 // Log the device's operational status if it's REBOOTED
955 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
956 "device-id": device.Id,
957 "OperStatus": device.OperStatus,
958 })
959 dh.lockDevice.RLock()
960 // Stop the read indication only if it the routine is active
961 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
962 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
963 // on next execution of the readIndication routine.
964 if dh.isHeartbeatCheckActive {
965 dh.stopHeartbeatCheck <- true
966 }
967 if dh.isReadIndicationRoutineActive {
968 dh.stopIndications <- true
969 }
bseenivaaa9165b2025-09-18 17:28:12 +0530970 if dh.isCollectorActive {
971 dh.stopCollector <- true
972 }
Nandita Biradar1b590f12024-09-27 10:56:28 +0530973 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +0530974 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +0530975 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
976 return fmt.Errorf("cleanup device resources failed: %w", err)
977 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530978 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +0530979 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
980 }
bseenivaaa9165b2025-09-18 17:28:12 +0530981 dh.collectorWaitGroup.Add(1)
982 go startCollector(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530983 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530984 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +0530985 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
986 // Log the device's operational status if it's RECONCILING
987 logger.Info(ctx, "Device is being reconciled", log.Fields{
988 "device-id": device.Id,
989 "OperStatus": device.OperStatus,
990 })
991
992 // Perform reconciliation steps
993 err = dh.reconcileOnus(ctx)
994 if err != nil {
995 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
996 }
997 err = dh.reconcilePonPorts(ctx)
998 if err != nil {
999 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301000 }
1001 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001002 // instantiate the mcast handler routines.
1003 for i := range dh.incomingMcastFlowOrGroup {
1004 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1005 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1006 if !dh.mcastHandlerRoutineActive[i] {
1007 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1008 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1009 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1010 // for incoming mcast flow/group to be processed serially.
1011 dh.mcastHandlerRoutineActive[i] = true
1012 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1013 }
1014 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301015 // Create DeviceStateFilter with the desired operational and connection statuses
1016 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001017 DeviceId: dh.device.Id,
1018 OperStatus: voltha.OperStatus_ACTIVE,
1019 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301020 }
1021 // Log DeviceStateFilter for debugging purposes
1022 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1023 "DeviceId": deviceStateFilter.DeviceId,
1024 "OperStatus": deviceStateFilter.OperStatus,
1025 "ConnStatus": deviceStateFilter.ConnStatus,
1026 })
1027 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301028 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001029 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001030 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001031
Akash Kankanala041a2122024-10-16 15:49:22 +05301032 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001033 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1034 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301035
1036 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1037 if err != nil {
1038 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1039 }
1040 dh.populateActivePorts(ctx, ports.Items)
1041 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1042 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1043 }
1044
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001045 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001046 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1047
Girish Gowdru0c588b22019-04-23 23:24:56 -04001048 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301049}
1050
1051// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301052func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001054
khenaidoo106c61a2021-08-11 18:05:46 -04001055 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001056 if err != nil || device == nil {
1057 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001058 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001059 }
1060
1061 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001062
Akash Kankanala041a2122024-10-16 15:49:22 +05301063 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001064 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001065 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001066 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001067 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001068
khenaidoodc2116e2021-10-19 17:33:19 -04001069 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001070 DeviceId: cloned.Id,
1071 OperStatus: cloned.OperStatus,
1072 ConnStatus: cloned.ConnectStatus,
1073 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001074 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001075 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001076
Akash Kankanala041a2122024-10-16 15:49:22 +05301077 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001078 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001079 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001080 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001081 }
1082 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001083 // Update onu state as down in onu adapter
1084 onuInd := oop.OnuIndication{}
1085 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001086
1087 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1088 if err != nil {
1089 return err
1090 }
1091 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001092 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001093 DeviceId: onuDevice.Id,
1094 OnuIndication: &onuInd,
1095 })
1096 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001098 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001099 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001100 "onu-indicator": onuInd,
1101 "device-type": onuDevice.Type,
1102 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301103 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001104 } else {
1105 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 -07001106 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001107 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001108 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001109 /* Discovered ONUs entries need to be cleared , since after OLT
1110 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301111 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001112 dh.lockDevice.Unlock()
1113
Neha Sharma96b7bf22020-06-15 10:37:32 +00001114 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001115 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301116}
1117
1118// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301119func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001120 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001121
1122 // if the connection is already available, close the previous connection (olt reboot case)
1123 if dh.clientCon != nil {
1124 if err = dh.clientCon.Close(); err != nil {
1125 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1126 } else {
1127 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1128 }
1129 }
1130
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301131 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001132 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001133 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1134 grpc.WithInsecure(),
1135 grpc.WithBlock(),
1136 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001137 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001138 )),
1139 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001140 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001141 )))
1142
1143 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301144 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301145 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001146 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001147 }
Akash Sonif49299a2024-04-25 12:06:37 +05301148 //Setting oper and connection state to RECONCILING and conn state to reachable
1149 cgClient, err := dh.coreClient.GetCoreServiceClient()
1150 if err != nil {
1151 return err
1152 }
1153
1154 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1155 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1156 defer cancel()
1157 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1158 DeviceId: dh.device.Id,
1159 OperStatus: voltha.OperStatus_RECONCILING,
1160 ConnStatus: voltha.ConnectStatus_REACHABLE,
1161 }); err != nil {
1162 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1163 }
1164 // 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
1165 // locally cached copy of the device struct.
1166 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1167 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1168 }
1169
Girish Gowdru0c588b22019-04-23 23:24:56 -04001170 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301171}
1172
1173// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301174func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001175 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301176 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001177 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301178}
1179
1180// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301181func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301182 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001183 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001184
1185 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001186 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301187 if err != nil || device == nil {
1188 /*TODO: needs to handle error scenarios */
1189 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1190 }
1191 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001192 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001193
1194 cloned := proto.Clone(device).(*voltha.Device)
1195 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1196 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1197 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001198
khenaidoodc2116e2021-10-19 17:33:19 -04001199 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001200 DeviceId: cloned.Id,
1201 OperStatus: cloned.OperStatus,
1202 ConnStatus: cloned.ConnectStatus,
1203 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301204 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 -04001205 }
1206
Chaitrashree G S44124192019-08-07 20:21:36 -04001207 // 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 +05301208 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001209 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301210 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001211 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001212 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1213 // all the modules initialized and ready to handle incoming ONUs.
1214
Thomas Lee S985938d2020-05-04 11:40:41 +05301215 err = dh.initializeDeviceHandlerModules(ctx)
1216 if err != nil {
1217 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 -04001218 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001219
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001220 go startHeartbeatCheck(ctx, dh)
1221
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001222 return nil
1223 }
1224
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001225 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301226 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 -04001227 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301228
Neha Sharma96b7bf22020-06-15 10:37:32 +00001229 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001230
1231 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001232 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001233 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001234
1235 go startHeartbeatCheck(ctx, dh)
1236
cuilin20187b2a8c32019-03-26 19:52:28 -07001237 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301238}
1239
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001240func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001241 var err error
1242 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001243
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001244 if dh.flowMgr != nil {
1245 dh.StopAllFlowRoutines(ctx)
1246 }
1247
1248 dh.CloseKVClient(ctx)
1249
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001250 if err != nil {
1251 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1252 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001253 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1254 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
bseenivaaa9165b2025-09-18 17:28:12 +05301255 // If collector go routine is active, wait for it to stop
1256 dh.lockDevice.RLock()
1257 if dh.isCollectorActive {
1258 dh.lockDevice.RUnlock()
1259 dh.collectorWaitGroup.Wait()
1260 } else {
1261 dh.lockDevice.RUnlock()
1262 }
yasin saplid0566272021-12-21 09:10:30 +00001263 // +1 is for NNI
1264 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1265 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001266 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001267 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1268 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1269 // There is only one NNI manager since multiple NNI is not supported for now
1270 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001271 // Instantiate resource manager
1272 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 -07001273 return olterrors.ErrResourceManagerInstantiating
1274 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001275 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001276 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1277 // the KV store to manage mcast group data. Provide the first instance (0th index)
1278 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1279 return olterrors.ErrGroupManagerInstantiating
1280 }
yasin saplid0566272021-12-21 09:10:30 +00001281 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001282 // Instantiate flow manager
1283 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301284 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001285 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1286 } else {
1287 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001288 }
1289 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001290 /* TODO: Instantiate Alarm , stats , BW managers */
1291 /* Instantiating Event Manager to handle Alarms and KPIs */
1292 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1293
1294 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001295 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001296
1297 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001298}
1299
Neha Sharma96b7bf22020-06-15 10:37:32 +00001300func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001301 var err error
1302 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301303 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001304
Neha Sharma8f4e4322020-08-06 10:51:53 +00001305 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001306
1307 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001308 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001309 }
1310 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001311 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001312 }
1313
Neha Sharma96b7bf22020-06-15 10:37:32 +00001314 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001315 dh.device.Root = true
1316 dh.device.Vendor = deviceInfo.Vendor
1317 dh.device.Model = deviceInfo.Model
1318 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1319 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1320 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1321
1322 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001323 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001324 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301325 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001326 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001327 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001328 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001329 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001330 dh.device.MacAddress = genmac
1331 } else {
1332 dh.device.MacAddress = deviceInfo.DeviceId
1333 }
1334
1335 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001336 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001337 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001338 }
1339
1340 return deviceInfo, nil
1341}
1342
Neha Sharma96b7bf22020-06-15 10:37:32 +00001343func startCollector(ctx context.Context, dh *DeviceHandler) {
bseenivaaa9165b2025-09-18 17:28:12 +05301344 logger.Infow(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001345
1346 defer func() {
1347 dh.lockDevice.Lock()
1348 dh.isCollectorActive = false
1349 dh.lockDevice.Unlock()
bseenivaaa9165b2025-09-18 17:28:12 +05301350 dh.collectorWaitGroup.Done()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001351 }()
1352
1353 dh.lockDevice.Lock()
1354 dh.isCollectorActive = true
1355 dh.lockDevice.Unlock()
1356
Naga Manjunath7615e552019-10-11 22:35:47 +05301357 for {
1358 select {
1359 case <-dh.stopCollector:
bseenivaaa9165b2025-09-18 17:28:12 +05301360 logger.Infow(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301361 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001362 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001363
khenaidoo106c61a2021-08-11 18:05:46 -04001364 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001365 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001366 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001367 continue
1368 }
khenaidoo106c61a2021-08-11 18:05:46 -04001369 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301370 // NNI Stats
1371 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001372 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301373 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001374 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001375 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001376 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301377 }
1378 // PON Stats
1379 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001380 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301381 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1382 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001383 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001384 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301385 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001386 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001387
yasin sapli9e4c5092022-02-01 13:52:33 +00001388 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001389 if len(onuGemInfoLst) > 0 {
1390 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001391 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001392 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301393 }
1394 }
1395 }
1396}
1397
Mahir Gunyela2e68702022-12-07 00:00:42 -08001398// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301399func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001400 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001401 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301402 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301403
1404 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001405 cgClient, err := dh.coreClient.GetCoreServiceClient()
1406 if err != nil {
1407 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1408 return
1409 }
1410
1411 // Now, set the initial PM configuration for that device
1412 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001413 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301414 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301415}
1416
Mahir Gunyela2e68702022-12-07 00:00:42 -08001417// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001418func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1419 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001420 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301421 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001422 HwDesc: "open_pon",
1423 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001424 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001425 },
1426 SwitchFeatures: &of.OfpSwitchFeatures{
1427 NBuffers: 256,
1428 NTables: 2,
1429 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1430 of.OfpCapabilities_OFPC_TABLE_STATS |
1431 of.OfpCapabilities_OFPC_PORT_STATS |
1432 of.OfpCapabilities_OFPC_GROUP_STATS),
1433 },
1434 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301435}
1436
khenaidoo106c61a2021-08-11 18:05:46 -04001437// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001438func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001439 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001440 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001441 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001442 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001443 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1444 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()
1445 }
khenaidoo106c61a2021-08-11 18:05:46 -04001446 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001447}
1448
Neha Sharma96b7bf22020-06-15 10:37:32 +00001449func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001450 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 -07001451 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452 var deviceID string
1453 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001454 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001455
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001456 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001457 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001458 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 -07001459 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1460 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001461
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001462 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301463
1464 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001465 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 -07001466 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001467
khenaidoodc2116e2021-10-19 17:33:19 -04001468 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001469 ParentId: dh.device.Id,
1470 OnuId: omciInd.OnuId,
1471 ParentPortNo: ponPort,
1472 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001473 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301474 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001475 "intf-id": omciInd.IntfId,
1476 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001477 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478 deviceType = onuDevice.Type
1479 deviceID = onuDevice.Id
1480 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001481 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301482 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001483 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001484 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301485 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001486 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 +05301487 deviceType = onuInCache.(*OnuDevice).deviceType
1488 deviceID = onuInCache.(*OnuDevice).deviceID
1489 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001490 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001491 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001492
khenaidoodc2116e2021-10-19 17:33:19 -04001493 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001494 ParentDeviceId: proxyDeviceID,
1495 ChildDeviceId: deviceID,
1496 Message: omciInd.Pkt,
1497 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301498 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001499 "source": dh.openOLT.config.AdapterEndpoint,
1500 "device-type": deviceType,
1501 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001502 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001503 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001504 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001505 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301506}
1507
khenaidoo106c61a2021-08-11 18:05:46 -04001508// //ProcessInterAdapterMessage sends the proxied messages to the target device
1509// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1510// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001511// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001512// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001513// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001514// return dh.handleInterAdapterOmciMsg(ctx, msg)
1515// }
1516// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1517// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001518
kesavandb9f54fd2021-11-25 20:08:04 +05301519// ProxyOmciRequests sends the proxied OMCI message to the target device
1520func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301521 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1522 return status.Error(codes.Unavailable, "OLT unreachable")
1523 }
kesavandb9f54fd2021-11-25 20:08:04 +05301524 if omciMsgs.GetProxyAddress() == nil {
1525 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1526 if err != nil {
1527 return olterrors.NewErrNotFound("onu", log.Fields{
1528 "parent-device-id": dh.device.Id,
1529 "child-device-id": omciMsgs.ChildDeviceId}, err)
1530 }
1531 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1532 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1533 return olterrors.NewErrCommunication("send-failed", log.Fields{
1534 "parent-device-id": dh.device.Id,
1535 "child-device-id": omciMsgs.ChildDeviceId}, err)
1536 }
1537 } else {
1538 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1539 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1540 return olterrors.NewErrCommunication("send-failed", log.Fields{
1541 "parent-device-id": dh.device.Id,
1542 "child-device-id": omciMsgs.ChildDeviceId}, err)
1543 }
1544 }
1545 return nil
1546}
1547
1548func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1549 var intfID uint32
1550 var onuID uint32
1551 var connectStatus common.ConnectStatus_Types
1552 if onuDevice != nil {
1553 intfID = onuDevice.ProxyAddress.GetChannelId()
1554 onuID = onuDevice.ProxyAddress.GetOnuId()
1555 connectStatus = onuDevice.ConnectStatus
1556 } else {
1557 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1558 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1559 connectStatus = omciMsgs.GetConnectStatus()
1560 }
1561 if connectStatus != voltha.ConnectStatus_REACHABLE {
1562 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1563
1564 return olterrors.NewErrCommunication("unreachable", log.Fields{
1565 "intf-id": intfID,
1566 "onu-id": onuID}, nil)
1567 }
1568
1569 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1570 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1571
1572 onuSecOmciMsgList := omciMsgs.GetMessages()
1573
1574 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301575 var omciMessage *oop.OmciMsg
1576 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1577 hex.Encode(hexPkt, onuSecOmciMsg)
1578 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1579
1580 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1581 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1582 //https://jira.opencord.org/browse/VOL-4604
1583 transid := extractOmciTransactionID(onuSecOmciMsg)
1584 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1585 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1586
1587 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1588 if err != nil {
1589 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1590 "intf-id": intfID,
1591 "onu-id": onuID,
1592 "message": omciMessage}, err)
1593 }
1594 }
1595 return nil
1596}
1597
khenaidoo106c61a2021-08-11 18:05:46 -04001598// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001599func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001600 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 -07001601
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301602 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1603 return status.Error(codes.Unavailable, "OLT unreachable")
1604 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001605 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001606 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001607 if err != nil {
1608 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001609 "parent-device-id": dh.device.Id,
1610 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001611 }
khenaidoo106c61a2021-08-11 18:05:46 -04001612 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1613 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001614 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001615 "parent-device-id": dh.device.Id,
1616 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001617 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001618 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001619 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1620 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001621 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001622 "parent-device-id": dh.device.Id,
1623 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001624 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001625 }
1626 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301627}
1628
khenaidoodc2116e2021-10-19 17:33:19 -04001629func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001630 var intfID uint32
1631 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001632 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001633 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001634 intfID = onuDevice.ProxyAddress.GetChannelId()
1635 onuID = onuDevice.ProxyAddress.GetOnuId()
1636 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001637 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001638 intfID = omciMsg.GetProxyAddress().GetChannelId()
1639 onuID = omciMsg.GetProxyAddress().GetOnuId()
1640 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001641 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001642 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001643 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 -08001644
Thomas Lee S94109f12020-03-03 16:39:29 +05301645 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001646 "intf-id": intfID,
1647 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001648 }
1649
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001650 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1651 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301652 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001653 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001654 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1655 hex.Encode(hexPkt, omciMsg.Message)
1656 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1657
1658 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1659 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1660 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001662 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001663
Neha Sharma8f4e4322020-08-06 10:51:53 +00001664 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001665 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301666 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001667 "intf-id": intfID,
1668 "onu-id": onuID,
1669 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001670 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001672}
1673
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301675 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 +00001676 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001677 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001678 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001679 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301680 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301681 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001682 st, _ := status.FromError(err)
1683 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001684 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 -04001685 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301686 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001687 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001688 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001689 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001690 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001692}
1693
Mahir Gunyela2e68702022-12-07 00:00:42 -08001694// getChildDevice function can be used in general to get child device, if not found in cache the function will
1695// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301696func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1697 var InCacheOnuDev *OnuDevice
1698 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1699 if onuInCache.(*OnuDevice).serialNumber == sn {
1700 InCacheOnuDev = onuInCache.(*OnuDevice)
1701 return false
1702 }
1703 return true
1704 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301705 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301706 if InCacheOnuDev != nil {
1707 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1708 return InCacheOnuDev
1709 }
1710 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1711 ParentId: dh.device.Id,
1712 SerialNumber: sn,
1713 ParentPortNo: parentPortNo,
1714 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301715 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301716 if onuDevice == nil {
1717 return nil
1718 }
1719 onuID := onuDevice.ProxyAddress.OnuId
1720 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1721 onuKey := dh.formOnuKey(intfID, onuID)
1722
1723 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1724 dh.onus.Store(onuKey, onuDev)
1725 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1726 return onuDev
1727}
1728
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301729// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1730// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301731func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001732 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301733 // 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 +05301734 // 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 +05301735 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1736 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1737 ParentId: dh.device.Id,
1738 SerialNumber: sn,
1739 ParentPortNo: parentPortNo,
1740 })
1741 if onuDevice != nil {
1742 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1743 return true, nil
1744 }
1745 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1746
1747 return false, nil
1748 } else {
1749 tpInstExists := false
1750 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301751 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1752 if onuDev != nil {
1753 var onuGemInfo *rsrcMgr.OnuGemInfo
1754 var err error
1755 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1756 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1757 return false, err
1758 }
1759 if onuGemInfo != nil {
1760 for _, uni := range onuGemInfo.UniPorts {
1761 uniID := plt.UniIDFromPortNum(uni)
1762 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1763 if len(tpIDs) != 0 {
1764 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1765 tpInstExists = true
1766 break
1767 }
1768 }
1769 }
1770 }
1771 return tpInstExists, nil
1772 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301773}
1774
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001775// processDiscONULOSClear clears the LOS Alarm if it's needed
1776func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301777 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001778 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301779
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001780 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1781 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1782 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1783 OnuLosRaise event sent for it */
1784 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1785 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1786 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1787 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1788 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1789 "currentIntfId": onuDiscInd.GetIntfId()})
1790 // TODO:: Should we need to ignore raising OnuLosClear event
1791 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301792 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001793 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1794 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1795 alarmInd.LosStatus = statusCheckOff
1796 go func() {
1797 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1798 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1799 }
1800 }()
1801 // stop iterating
1802 return false
1803 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301804 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001805 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301806}
1807
bseeniva43b5a912025-06-05 12:48:15 +05301808func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1809 if err != nil || tpInstExists {
1810 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1811 } else {
1812 // once the function completes set the value to false so that
1813 // we know the processing has inProcess.
1814 // Note that this is done after checking if we are already processing
1815 // to avoid changing the value from a different thread
1816 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1817 dh.discOnus.Store(sn, false)
1818 }
1819}
1820
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301821func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301822 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301823 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301824
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301825 channelID := onuDiscInd.GetIntfId()
1826 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1827
1828 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301829 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301830 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301831 }()
1832
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301833 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1834
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301835 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1836 if !dh.cfg.ForceOnuDiscIndProcessing {
1837 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1838 if error != nil {
1839 return error
1840 }
1841 if tpInstExists {
1842 // ignore the discovery if tpinstance is present.
1843 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1844 return nil
1845 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001846 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001847 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1848
1849 // if the ONU existed, handle the LOS Alarm
1850 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001851 if inProcess.(bool) {
1852 // if we're currently processing the ONU on a different thread, do nothing
1853 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1854 return nil
1855 }
1856 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1857 // then continue processing it
1858 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1859
1860 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001861 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301862 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001863 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001864
1865 // check the ONU is already know to the OLT
1866 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301867 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001868 ParentId: dh.device.Id,
1869 SerialNumber: sn,
1870 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001871
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301872 if error != nil {
1873 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1874 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 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 -08001876 switch e.Code() {
1877 case codes.Internal:
1878 // this probably means NOT FOUND, so just create a new device
1879 onuDevice = nil
1880 case codes.DeadlineExceeded:
1881 // if the call times out, cleanup and exit
1882 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301883 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1884 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001885 }
1886 }
1887 }
1888
1889 if onuDevice == nil {
1890 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001891 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001892 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001893 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301894 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001895 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001896
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301897 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001898 // if we can't create an ID in resource manager,
1899 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001900 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301901
1902 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001903 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301904 "serial-number": sn}, error)
1905 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001906 }
1907
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301908 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001909 ParentId: dh.device.Id,
1910 ParentPortNo: parentPortNo,
1911 ChannelId: channelID,
1912 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1913 SerialNumber: sn,
1914 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301915 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001916 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001917 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 +05301918
1919 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001920 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301921 "serial-number": sn}, error)
1922 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001923 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301924 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 +05301925 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1926 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1927 "onu-id": onuID,
1928 "device-id": dh.device.Id,
1929 "serial-number": sn}, error)
1930 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001931 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301933 log.Fields{"onuDevice": onuDevice,
1934 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001935 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301936 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001937 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001938
khenaidoo106c61a2021-08-11 18:05:46 -04001939 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1940 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301941 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001942 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301943 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301944 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1945 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001946 }
1947
Matteo Scandolo945e4012019-12-12 14:16:11 -08001948 // we can now use the existing ONU Id
1949 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05301950 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001951 //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 +00001952 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001953 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301954 "intfId": onuDiscInd.GetIntfId(),
1955 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001956 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001957
khenaidoo106c61a2021-08-11 18:05:46 -04001958 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301959 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301961 log.Fields{"onu": onuDev,
1962 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001963
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301964 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001965 DeviceId: onuDevice.Id,
1966 ParentDeviceId: dh.device.Id,
1967 OperStatus: common.OperStatus_DISCOVERED,
1968 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301969 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301970 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001971 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301972 "serial-number": sn}, error)
1973 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001974 }
khenaidoo106c61a2021-08-11 18:05:46 -04001975
Neha Sharma96b7bf22020-06-15 10:37:32 +00001976 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301977 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301978 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001979 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301980 "serial-number": sn}, error)
1981 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001982 }
1983 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001984}
1985
Mahir Gunyelb0046752021-02-26 13:51:05 -08001986func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001987 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001988 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001989 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001990 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001991 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301992 log.Fields{"onuId": onuInd.OnuId,
1993 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301994 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001995 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001996 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001997 errFields := log.Fields{"device-id": dh.device.Id}
1998
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301999 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05302000 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07002001 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002002 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002003 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002004 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302005 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07002006 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002007 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002008 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002009 errFields["onu-id"] = onuInd.OnuId
2010 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002011 }
khenaidoodc2116e2021-10-19 17:33:19 -04002012 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002013 ParentId: dh.device.Id,
2014 SerialNumber: serialNumber,
2015 OnuId: onuInd.OnuId,
2016 ParentPortNo: ponPort,
2017 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002018 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002019
David K. Bainbridge794735f2020-02-11 21:01:37 -08002020 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002021 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002022 }
2023
David K. Bainbridge794735f2020-02-11 21:01:37 -08002024 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002025 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002026 "previousIntfId": onuDevice.ParentPortNo,
2027 "currentIntfId": ponPort})
2028 }
2029
2030 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302032 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2033 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302034 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002035 }
2036 if !foundInCache {
2037 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002038 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 -08002039 }
kesavand7cf3a052020-08-28 12:49:18 +05302040 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002041 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002042 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302043 }
2044 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002045 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002046 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002047 }
2048 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002049}
2050
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002052 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 -07002053 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2054 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2055 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2056 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002057 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002058 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2059 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002061 onuInd.OperState = "down"
2062 }
2063 }
2064
David K. Bainbridge794735f2020-02-11 21:01:37 -08002065 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002066 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002067 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 -04002068
khenaidoodc2116e2021-10-19 17:33:19 -04002069 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002070 DeviceId: onuDevice.Id,
2071 OnuIndication: onuInd,
2072 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002073 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302074 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002075 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002076 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002077 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002078 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002079 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002080 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002081 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002082 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002083 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002084}
2085
cuilin20187b2a8c32019-03-26 19:52:28 -07002086func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2087 if serialNum != nil {
2088 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002089 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002090 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002091}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002092func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2093 decodedStr, err := hex.DecodeString(serialNum[4:])
2094 if err != nil {
2095 return nil, err
2096 }
2097 return &oop.SerialNumber{
2098 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002099 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002100 }, nil
2101}
cuilin20187b2a8c32019-03-26 19:52:28 -07002102
2103func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002104 if len(vendorSpecific) > 3 {
2105 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2106 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2107 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2108 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2109 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2110 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2111 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2112 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2113 return tmp
2114 }
2115 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002116}
2117
Mahir Gunyela2e68702022-12-07 00:00:42 -08002118// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002119func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302120 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002121}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002122
Mahir Gunyela2e68702022-12-07 00:00:42 -08002123// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002124func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2125 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302126 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002127 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302128 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002129
khenaidoodc2116e2021-10-19 17:33:19 -04002130 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002131 ParentId: dh.device.Id,
2132 OnuId: onuID,
2133 ParentPortNo: parentPort,
2134 })
2135
Girish Gowdru0c588b22019-04-23 23:24:56 -04002136 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002137 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002138 "intf-id": parentPort,
2139 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002140 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141 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 -08002142 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302143}
2144
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002145// SendPacketInToCore sends packet-in to core
2146// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2147// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002148func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002149 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002151 "port": logicalPort,
2152 "packet": hex.EncodeToString(packetPayload),
2153 "device-id": dh.device.Id,
2154 })
2155 }
khenaidoo106c61a2021-08-11 18:05:46 -04002156
khenaidoodc2116e2021-10-19 17:33:19 -04002157 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002158 DeviceId: dh.device.Id,
2159 Port: logicalPort,
2160 Packet: packetPayload,
2161 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302162 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002163 "source": "adapter",
2164 "destination": "core",
2165 "device-id": dh.device.Id,
2166 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002167 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002168 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002169 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002170 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002171 "packet": hex.EncodeToString(packetPayload),
2172 "device-id": dh.device.Id,
2173 })
2174 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002175 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002176}
2177
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002178// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002179func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002180 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002181
2182 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2183 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002185 }
2186
Kent Hagermane6ff1012020-07-14 15:07:53 -04002187 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002188 metrics := dh.metrics.GetSubscriberMetrics()
2189 for _, m := range pmConfigs.Metrics {
2190 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002191 }
2192 }
2193}
2194
khenaidoodc2116e2021-10-19 17:33:19 -04002195func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002196 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002197 var errorsList []error
2198
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002199 if dh.getDeviceDeletionInProgressFlag() {
2200 // The device itself is going to be reset as part of deletion. So nothing to be done.
2201 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2202 return nil
2203 }
2204
Girish Gowdru0c588b22019-04-23 23:24:56 -04002205 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002206 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302207 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002208
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302210 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002211 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302212 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002213 if flow_utils.HasGroup(flow) {
2214 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2215 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002216 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2217 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2218 } else {
2219 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2220 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002221 }
Girish Gowdracefae192020-03-19 18:14:10 -07002222 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002223 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302224 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002225 logger.Warnw(ctx, "flow-to-remove-not-found",
2226 log.Fields{
2227 "ponIf": intfID,
2228 "flowToRemove": flow,
2229 "error": err,
2230 })
2231 } else {
2232 errorsList = append(errorsList, err)
2233 }
Girish Gowdracefae192020-03-19 18:14:10 -07002234 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002235 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302236
2237 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302238 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002239 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302240 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002241 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302242 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002243 if flow_utils.HasGroup(flow) {
2244 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2245 } else {
yasin saplid0566272021-12-21 09:10:30 +00002246 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002247 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2248 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2249 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2250 } else {
yasin saplid0566272021-12-21 09:10:30 +00002251 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002252 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002253 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002254 if err != nil {
2255 errorsList = append(errorsList, err)
2256 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302257 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002258 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002259
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002260 return errorsList
2261}
2262
2263func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2264 var err error
2265 var errorsList []error
2266
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002267 if dh.getDeviceDeletionInProgressFlag() {
2268 // The device itself is going to be reset as part of deletion. So nothing to be done.
2269 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2270 return nil
2271 }
2272
Girish Gowdracefae192020-03-19 18:14:10 -07002273 // 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 +00002274 if groups != nil {
2275 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002276 // err = dh.groupMgr.AddGroup(ctx, group)
2277 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002278 if err != nil {
2279 errorsList = append(errorsList, err)
2280 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002281 }
2282 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002283 // err = dh.groupMgr.ModifyGroup(ctx, group)
2284 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002285 if err != nil {
2286 errorsList = append(errorsList, err)
2287 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002288 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002289 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002290 // err = dh.groupMgr.DeleteGroup(ctx, group)
2291 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002292 if err != nil {
2293 errorsList = append(errorsList, err)
2294 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002295 }
2296 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002297
2298 return errorsList
2299}
2300
Mahir Gunyela2e68702022-12-07 00:00:42 -08002301// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002302func (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 -07002303 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002304
2305 if dh.getDeviceDeletionInProgressFlag() {
2306 // The device itself is going to be reset as part of deletion. So nothing to be done.
2307 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2308 return nil
2309 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302310 if dh.transitionMap.currentDeviceState != deviceStateUp {
2311 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2312 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2313 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002314 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2315 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2316 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002317 if len(errorsList) > 0 {
2318 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2319 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002320 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002321 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302322}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002323
Mahir Gunyela2e68702022-12-07 00:00:42 -08002324// DisableDevice disables the given device
2325// It marks the following for the given device:
2326// Device-Handler Admin-State : down
2327// Device Port-State: UNKNOWN
2328// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002330 /* On device disable ,admin state update has to be done prior sending request to agent since
2331 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002332 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002333 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002334 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002335 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002336 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002337 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002338 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002340 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002341 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302342
2343 dh.discOnus = sync.Map{}
2344 dh.onus = sync.Map{}
2345
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002346 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302347 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002348 if dh.isCollectorActive {
2349 dh.stopCollector <- true
2350 }
2351 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302352
Neha Sharma96b7bf22020-06-15 10:37:32 +00002353 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002354 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302355 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302356 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002357
kdarapu1afeceb2020-02-12 01:38:09 -05002358 // 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 -04002359 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002360 DeviceId: cloned.Id,
2361 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2362 OperStatus: voltha.OperStatus_UNKNOWN,
2363 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002364 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002365 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002366 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002367 return nil
2368}
2369
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002371 // Update onu state as unreachable in onu adapter
2372 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302373 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002374
Akash Kankanala041a2122024-10-16 15:49:22 +05302375 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002376 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002377 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002378 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 -04002379 }
2380 if onuDevices != nil {
2381 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002382 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002383 DeviceId: onuDevice.Id,
2384 OnuIndication: &onuInd,
2385 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002386 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002388 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002389 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002390 }
2391 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002392}
2393
Mahir Gunyela2e68702022-12-07 00:00:42 -08002394// ReenableDevice re-enables the olt device after disable
2395// It marks the following for the given device:
2396// Device-Handler Admin-State : up
2397// Device Port-State: ACTIVE
2398// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002399func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302400 if dh.Client != nil {
2401 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2402 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2403 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2404 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302405 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302406 } else {
2407 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 +05302408 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002409 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002410
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002411 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002412 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002413 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002414 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002415 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2416 } else {
2417 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2418 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2419 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002420 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002421 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302422 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002423 device.OperStatus = voltha.OperStatus_ACTIVE
2424 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302425 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002426 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002427 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002428 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002429
khenaidoodc2116e2021-10-19 17:33:19 -04002430 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002431 DeviceId: device.Id,
2432 OperStatus: device.OperStatus,
2433 ConnStatus: device.ConnectStatus,
2434 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302435 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002436 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002437 "connect-status": device.ConnectStatus,
2438 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002439 }
kesavand39e0aa32020-01-28 20:58:50 -05002440
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002442
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002443 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002444}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002445
npujarec5762e2020-01-01 14:08:48 +05302446func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002447 var uniID uint32
2448 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002449 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302450 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002451 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002452 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002453 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002454 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2455 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2456 } else {
2457 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2458 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002459 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002460 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002461 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002462 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002463 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002464 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002465 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002466 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002467 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002468 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002469 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002470 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002471 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002472 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002473 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002474 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302475 }
yasin saplibddc2d72022-02-08 13:10:17 +00002476 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2477 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002478 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002479 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302480 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002481 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002482 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 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 -03002484 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002485 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002486 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002487 if len(errs) > 0 {
2488 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2489 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2490 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002491 return nil
2492}
2493
Devmalya Paul495b94a2019-08-27 19:42:00 -04002494// 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 +05302495func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002496 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002497 /* Clear the KV store data associated with the all the UNI ports
2498 This clears up flow data and also resource map data for various
2499 other pon resources like alloc_id and gemport_id
2500 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002501
2502 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002503 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002504
Himani Chawla49a5d562020-11-25 11:53:44 +05302505 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002506 // Stop the Stats collector
2507 if dh.isCollectorActive {
2508 dh.stopCollector <- true
2509 }
2510 // stop the heartbeat check routine
2511 if dh.isHeartbeatCheckActive {
2512 dh.stopHeartbeatCheck <- true
2513 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302514 // Stop the read indication only if it the routine is active
2515 if dh.isReadIndicationRoutineActive {
2516 dh.stopIndications <- true
2517 }
2518 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302519
2520 err := dh.cleanupDeviceResources(ctx)
2521 if err != nil {
2522 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2523 } else {
2524 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2525 }
2526
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002527 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302528 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002529 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302530 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002531 go func() {
2532 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302533 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2534 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002535 }
2536 }()
2537 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002538 }
2539 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002540 // There is no need to update the core about operation status and connection status of the OLT.
2541 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2542 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2543 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002544
khenaidoo7eb2d672021-10-22 19:08:50 -04002545 // Stop the adapter grpc clients for that parent device
2546 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002547 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002548}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002549
2550// StopAllFlowRoutines stops all flow routines
2551func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2552 var wg sync.WaitGroup
2553 wg.Add(1) // for the mcast routine below to finish
2554 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2555 for _, flMgr := range dh.flowMgr {
2556 if flMgr != nil {
2557 wg.Add(1) // for the flow handler routine below to finish
2558 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2559 }
2560 }
2561 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2562 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2563 } else {
2564 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2565 }
2566}
2567
Gustavo Silva41af9122022-10-11 11:05:13 -03002568func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2569 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002570 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302571 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002572 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002573 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002574 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002575 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002576 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2577 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302578 }
2579 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002580 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2581 errs = append(errs, err)
2582 }
2583 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2584 errs = append(errs, err)
2585 }
2586 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2587 errs = append(errs, err)
2588 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002589 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002590 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002591 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002592 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002593 }
2594 // Clean up NNI manager's data
2595 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2596 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002597 }
A R Karthick1f85b802019-10-11 05:06:05 +00002598
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002599 dh.CloseKVClient(ctx)
2600
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002601 // Take one final sweep at cleaning up KV store for the OLT device
2602 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002603 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2604 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002605 }
2606
Devmalya Paul495b94a2019-08-27 19:42:00 -04002607 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302608 dh.onus.Range(func(key interface{}, value interface{}) bool {
2609 dh.onus.Delete(key)
2610 return true
2611 })
2612
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002613 /*Delete discovered ONU map for the device*/
2614 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2615 dh.discOnus.Delete(key)
2616 return true
2617 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002618 if len(errs) > 0 {
2619 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2620 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2621 }
2622 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002623}
2624
Mahir Gunyela2e68702022-12-07 00:00:42 -08002625// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002626func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302627 if dh.Client != nil {
2628 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2629 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2630 }
2631 } else {
2632 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 -04002633 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302634
Neha Sharma96b7bf22020-06-15 10:37:32 +00002635 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002636 return nil
2637}
2638
David K. Bainbridge794735f2020-02-11 21:01:37 -08002639func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002640 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002641 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002642 "packet-indication": *packetIn,
2643 "device-id": dh.device.Id,
2644 "packet": hex.EncodeToString(packetIn.Pkt),
2645 })
2646 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002647 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2648 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2649 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002650 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002651 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002652 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002654 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002655 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002656 "logical-port-num": logicalPortNum,
2657 "device-id": dh.device.Id,
2658 "packet": hex.EncodeToString(packetIn.Pkt),
2659 })
2660 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002661
khenaidoodc2116e2021-10-19 17:33:19 -04002662 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002663 DeviceId: dh.device.Id,
2664 Port: logicalPortNum,
2665 Packet: packetIn.Pkt,
2666 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302667 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302669 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002670 "device-id": dh.device.Id,
2671 "packet": hex.EncodeToString(packetIn.Pkt),
2672 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002673 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002674
Matteo Scandolo92186242020-06-12 10:54:18 -07002675 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002676 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002677 "packet": hex.EncodeToString(packetIn.Pkt),
2678 "device-id": dh.device.Id,
2679 })
2680 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002681 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002682}
2683
Mahir Gunyela2e68702022-12-07 00:00:42 -08002684// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2685func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2686 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2687 if err != nil {
2688 return olterrors.NewErrInvalidValue(log.Fields{
2689 "egress-nni-port": egressPortNo,
2690 "device-id": dh.device.Id,
2691 }, err)
2692 }
2693 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2694
2695 if logger.V(log.DebugLevel) {
2696 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2697 "uplink-pkt": uplinkPkt,
2698 "packet": hex.EncodeToString(packet.Data),
2699 "device-id": dh.device.Id,
2700 })
2701 }
2702
2703 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2704 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2705 "packet": hex.EncodeToString(packet.Data),
2706 "device-id": dh.device.Id,
2707 }, err)
2708 }
2709 return nil
2710}
2711
2712// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2713func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2714 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2715 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2716 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2717 // Do not packet-out lldp packets on uni port.
2718 // ONOS has no clue about uni/nni ports, it just packets out on all
2719 // available ports on the Logical Switch. It should not be interested
2720 // in the UNI links.
2721 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2722 "device-id": dh.device.Id,
2723 })
2724 return nil
2725 }
2726 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2727 if innerEthType == 0x8100 {
2728 // q-in-q 802.1ad or 802.1q double tagged packet.
2729 // slice out the outer tag.
2730 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2731 if logger.V(log.DebugLevel) {
2732 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2733 "packet-data": hex.EncodeToString(packet.Data),
2734 "device-id": dh.device.Id,
2735 })
2736 }
2737 }
2738 }
2739 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2740 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2741 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2742 var gemPortID uint32
2743 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2744 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2745 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2746 }
2747 if err != nil {
2748 // In this case the openolt agent will receive the gemPortID as 0.
2749 // The agent tries to retrieve the gemPortID in this case.
2750 // This may not always succeed at the agent and packetOut may fail.
2751 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2752 "intf-id": intfID,
2753 "onu-id": onuID,
2754 "uni-id": uniID,
2755 "packet": hex.EncodeToString(packet.Data),
2756 "device-id": dh.device.Id,
2757 "error": err,
2758 })
2759 }
2760
2761 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2762 if logger.V(log.DebugLevel) {
2763 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2764 "egress-port-no": egressPortNo,
2765 "intf-id": intfID,
2766 "onu-id": onuID,
2767 "uni-id": uniID,
2768 "gem-port-id": gemPortID,
2769 "packet": hex.EncodeToString(packet.Data),
2770 "device-id": dh.device.Id,
2771 })
2772 }
2773
2774 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2775 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2776 "source": "adapter",
2777 "destination": "onu",
2778 "egress-port-number": egressPortNo,
2779 "intf-id": intfID,
2780 "oni-id": onuID,
2781 "uni-id": uniID,
2782 "gem-port-id": gemPortID,
2783 "packet": hex.EncodeToString(packet.Data),
2784 "device-id": dh.device.Id,
2785 }, err)
2786 }
2787 return nil
2788}
2789
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002790// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002791func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002792 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002793 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002794 "device-id": dh.device.Id,
2795 "egress-port-no": egressPortNo,
2796 "pkt-length": len(packet.Data),
2797 "packet": hex.EncodeToString(packet.Data),
2798 })
2799 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002800
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002801 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002802 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002803 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002804 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002805 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002806 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002807 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002808 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302809 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002810 "egressPortType": egressPortType,
2811 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302812 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002813 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002814 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002815 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002816}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002817
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002818func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2819 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002820}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302821
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002822func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002823 defer func() {
2824 dh.lockDevice.Lock()
2825 dh.isHeartbeatCheckActive = false
2826 dh.lockDevice.Unlock()
2827 }()
2828
2829 dh.lockDevice.Lock()
2830 dh.isHeartbeatCheckActive = true
2831 dh.lockDevice.Unlock()
2832
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302833 // start the heartbeat check towards the OLT.
2834 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302835 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302836
2837 for {
2838 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2839 select {
2840 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002841 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002842 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002843 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302844 if timerCheck == nil {
2845 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002846 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302847 }
2848 } else {
2849 if timerCheck != nil {
2850 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002851 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302852 }
2853 timerCheck = nil
2854 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302855 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2856 if dh.heartbeatSignature == 0 {
2857 // First time the signature will be 0, update the signture to DB when not found.
2858 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2859 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2860 }
2861 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2862
2863 dh.lockDevice.RLock()
2864 // Stop the read indication only if it the routine is active
2865 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2866 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2867 // on next execution of the readIndication routine.
2868 if !dh.isReadIndicationRoutineActive {
2869 // Start reading indications
2870 go func() {
2871 if err = dh.readIndications(ctx); err != nil {
2872 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2873 }
2874 }()
2875 }
2876 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302877 } else {
2878 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2879 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2880 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2881 go dh.updateStateRebooted(ctx)
2882 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302883 }
2884 cancel()
2885 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002886 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302887 return
2888 }
2889 }
2890}
2891
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002892func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002893 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002894 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002895 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2896 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2897 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2898 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2899 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002900 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002901 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2902 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002903 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302904
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302905 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002906 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002907 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002908 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002909 DeviceId: dh.device.Id,
2910 OperStatus: voltha.OperStatus_UNKNOWN,
2911 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2912 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002913 _ = 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 -04002914 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302915 /*
2916 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2917 DeviceId: dh.device.Id,
2918 PortTypeFilter: 0,
2919 OperStatus: voltha.OperStatus_UNKNOWN,
2920 }); err != nil {
2921 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2922 }
2923 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002924
Akash Kankanala041a2122024-10-16 15:49:22 +05302925 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002926 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002927 cloned := proto.Clone(device).(*voltha.Device)
2928 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2929 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2930 dh.device = cloned // update local copy of the device
2931 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002932
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002933 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002934 // Stop the Stats collector
2935 if dh.isCollectorActive {
2936 dh.stopCollector <- true
2937 }
2938 // stop the heartbeat check routine
2939 if dh.isHeartbeatCheckActive {
2940 dh.stopHeartbeatCheck <- true
2941 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002942 // Stop the read indication only if it the routine is active
2943 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2944 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2945 // on next execution of the readIndication routine.
2946 if dh.isReadIndicationRoutineActive {
2947 dh.stopIndications <- true
2948 }
2949 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002950 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302951 }
2952}
kesavand39e0aa32020-01-28 20:58:50 -05002953
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302954func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2955 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2956 if err != nil || device == nil {
2957 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2958 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2959 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2960 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2961 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2962 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2963 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2964 return
2965 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302966 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07002967 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302968
2969 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2970 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05302971 // First, stop the read indication and heartbeat check routines to prevent any delay
2972 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302973 dh.lockDevice.RLock()
2974 // Stop the read indication only if it the routine is active
2975 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2976 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2977 // on next execution of the readIndication routine.
2978 if dh.isReadIndicationRoutineActive {
2979 dh.stopIndications <- true
2980 }
2981 dh.lockDevice.RUnlock()
2982
bseenivad1c984b2025-01-09 12:54:44 +05302983 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2984 DeviceId: dh.device.Id,
2985 OperStatus: voltha.OperStatus_REBOOTED,
2986 ConnStatus: voltha.ConnectStatus_REACHABLE,
2987 }); err != nil {
2988 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2989 }
2990
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302991 //raise olt communication failure event
2992 raisedTs := time.Now().Unix()
2993 cloned := proto.Clone(device).(*voltha.Device)
2994 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2995 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2996 dh.device = cloned // update local copy of the device
2997 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2998
Gustavo Silva41af9122022-10-11 11:05:13 -03002999 if err := dh.cleanupDeviceResources(ctx); err != nil {
3000 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3001 } else {
3002 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3003 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003004
3005 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303006 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003007 if dh.isCollectorActive {
3008 dh.stopCollector <- true
3009 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303010 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003011 if dh.isHeartbeatCheckActive {
3012 dh.stopHeartbeatCheck <- true
3013 }
3014 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303015
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003016 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303017
Akash Kankanala041a2122024-10-16 15:49:22 +05303018 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303019 dh.adapterPreviouslyConnected = false
3020 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303021 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3022 if err != nil || childDevices == nil {
3023 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3024 continue
3025 }
3026 if len(childDevices.Items) == 0 {
3027 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3028 break
3029 } else {
3030 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3031 time.Sleep(5 * time.Second)
3032 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303033 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303034 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003035 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303036 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3037 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303038}
3039
kesavand39e0aa32020-01-28 20:58:50 -05003040// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003041func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3042 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3043 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003044}
3045
3046// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3048 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3049 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003050}
3051
Mahir Gunyela2e68702022-12-07 00:00:42 -08003052// 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 +00003053func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3054 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003055 if port.GetType() == voltha.Port_ETHERNET_NNI {
3056 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003057 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303058 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303059 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003060 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003061 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003062 }
3063 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003064 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003065 ponIntf := &oop.Interface{IntfId: ponID}
3066 var operStatus voltha.OperStatus_Types
3067 if enablePort {
3068 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303069 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003070
3071 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303072 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003073 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003074 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003075 }
3076 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003077 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003079 } else {
3080 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303081 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003082 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303083 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003084 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003085 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003086 }
3087 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003088 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003090 }
khenaidoodc2116e2021-10-19 17:33:19 -04003091 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003092 DeviceId: dh.device.Id,
3093 PortType: voltha.Port_PON_OLT,
3094 PortNo: port.PortNo,
3095 OperStatus: operStatus,
3096 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303097 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303098 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003099 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003100 }
3101 return nil
3102}
3103
Mahir Gunyela2e68702022-12-07 00:00:42 -08003104// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003105func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003106 // Disable the port and update the oper_port_status to core
3107 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003108 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003109 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003110 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303111 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303112 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003113 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003114 }
3115 }
3116 }
3117 return nil
3118}
3119
Mahir Gunyela2e68702022-12-07 00:00:42 -08003120// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003121func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3122 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3123 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003124 if port.Type == voltha.Port_ETHERNET_NNI {
3125 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003126 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003127 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003128 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003129 }
3130 }
3131 if port.Type == voltha.Port_PON_OLT {
3132 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003133 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003134 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003135 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003136 }
3137 }
3138 }
3139}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003140
3141// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003142func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003143 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003144 if dh.getDeviceDeletionInProgressFlag() {
3145 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3146 // will reboot, so everything will be reset on the pOLT too.
3147 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3148 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3149 return nil
3150 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303151
3152 if dh.transitionMap.currentDeviceState != deviceStateUp {
3153 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})
3154 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3155 }
3156
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003157 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003158 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003159
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003160 var sn *oop.SerialNumber
3161 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003162 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303163 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003164 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303165 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003166 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003167 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003168
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003169 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303170 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003171 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003172 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3173 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3174 "device-id": dh.device.Id,
3175 "intf-id": intfID,
3176 "onuID": onuID,
3177 "err": err})
3178 } else {
3179 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003180 // Delete flows from device before schedulers and queue
3181 // Clear flowids for gem cache.
3182 removedFlows := []uint64{}
3183 for _, gem := range onuGem.GemPorts {
3184 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3185 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303186 // multiple gem port can have the same flow id
3187 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003188 var alreadyRemoved bool
3189 for _, removedFlowID := range removedFlows {
3190 if removedFlowID == flowID {
3191 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3192 alreadyRemoved = true
3193 break
3194 }
3195 }
3196 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003197 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003198 removedFlows = appendUnique64bit(removedFlows, flowID)
3199 }
3200 }
3201 }
3202 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3203 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003204 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3205 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3206 "device-id": dh.device.Id,
3207 "onu-device": onu,
3208 "err": err})
3209 }
yasin saplibddc2d72022-02-08 13:10:17 +00003210 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003211 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3212 "intf-id": intfID,
3213 "onu-device": onu,
3214 "onu-gem": onuGem,
3215 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303216 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003217 }
3218 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003219 }
yasin saplibddc2d72022-02-08 13:10:17 +00003220 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003221 dh.onus.Delete(onuKey)
3222 dh.discOnus.Delete(onuSn)
3223
3224 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003225 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303226 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303227 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003228 "onu-id": onuID}, err).Log()
3229 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003230
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003231 return nil
3232}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003233func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3234 flow := &oop.Flow{FlowId: flowID}
3235 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3236 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3237 "device-id": dh.device.Id})
3238 } else {
3239 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3240 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3241 "device-id": dh.device.Id,
3242 "err": err})
3243 }
3244 }
3245}
Girish Gowdracefae192020-03-19 18:14:10 -07003246
3247func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003248 for _, field := range flow_utils.GetOfbFields(flow) {
3249 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003250 return field.GetPort()
3251 }
3252 }
3253 return InvalidPort
3254}
3255
3256func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003257 for _, action := range flow_utils.GetActions(flow) {
3258 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003259 if out := action.GetOutput(); out != nil {
3260 return out.GetPort()
3261 }
3262 }
3263 }
3264 return InvalidPort
3265}
3266
Girish Gowdracefae192020-03-19 18:14:10 -07003267func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3268 inPort := getInPortFromFlow(flow)
3269 outPort := getOutPortFromFlow(flow)
3270
3271 if inPort == InvalidPort || outPort == InvalidPort {
3272 return inPort, outPort
3273 }
3274
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003275 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003276 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003277 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003278 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003279 return uniPort, outPort
3280 }
3281 }
3282 } else {
3283 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003284 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003285 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003286 return inPort, uniPort
3287 }
3288 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003289 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003290 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003291 return uniPort, outPort
3292 }
3293 }
3294 }
3295
3296 return InvalidPort, InvalidPort
3297}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003298
3299func extractOmciTransactionID(omciPkt []byte) uint16 {
3300 if len(omciPkt) > 3 {
3301 d := omciPkt[0:2]
3302 transid := binary.BigEndian.Uint16(d)
3303 return transid
3304 }
3305 return 0
3306}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003307
3308// StoreOnuDevice stores the onu parameters to the local cache.
3309func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3310 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3311 dh.onus.Store(onuKey, onuDevice)
3312}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003313
khenaidoodc2116e2021-10-19 17:33:19 -04003314func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003315 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003316 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003317 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003318 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003319 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003320 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003321 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003322 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3323 return nil, err
3324 }
3325 ID = device.ProxyAddress.GetOnuId()
3326 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3327 valueparam.Onu = &Onu
3328 valueparam.Value = value
3329
3330 // This API is unsupported until agent patch is added
3331 resp.Unsupported = uint32(value)
3332 _ = ctx
3333
3334 // Uncomment this code once agent changes are complete and tests
3335 /*
3336 resp, err = dh.Client.GetValue(ctx, valueparam)
3337 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003338 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003339 return nil, err
3340 }
3341 */
3342
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003343 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 -08003344 return resp, nil
3345}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003346
Akash Kankanala041a2122024-10-16 15:49:22 +05303347func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003348 // Default to NNI
3349 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003350 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003351 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003352 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003353 }
3354 return intfID
3355}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003356
Akash Kankanala041a2122024-10-16 15:49:22 +05303357func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003358 dh.perPonOnuIndicationChannelLock.Lock()
3359 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3360 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003361 return ch.indicationChannel
3362 }
3363 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303364 // We create a buffered channel here to avoid calling function to be blocked
3365 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003366 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003367 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003368 stopChannel: make(chan struct{}),
3369 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003370 dh.perPonOnuIndicationChannel[intfID] = channels
3371 dh.perPonOnuIndicationChannelLock.Unlock()
3372 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003373 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003374}
3375
Mahir Gunyelb0046752021-02-26 13:51:05 -08003376func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3377 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3378 dh.perPonOnuIndicationChannelLock.Lock()
3379 defer dh.perPonOnuIndicationChannelLock.Unlock()
3380 for _, v := range dh.perPonOnuIndicationChannel {
3381 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003382 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003383 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003384}
3385
Mahir Gunyelb0046752021-02-26 13:51:05 -08003386func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3387 ind := onuIndicationMsg{
3388 ctx: ctx,
3389 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003390 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003391 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003392 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303393 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003394}
3395
Mahir Gunyelb0046752021-02-26 13:51:05 -08003396func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003397 for {
3398 select {
3399 // process one indication per onu, before proceeding to the next one
3400 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003401 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003402 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003403 "ind": indication})
3404 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003405 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003406 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003407 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3408 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003409 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003410 }
3411 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003412 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003413 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3414 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003415 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003416 }
3417 }
3418 case <-onuChannels.stopChannel:
3419 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3420 close(onuChannels.indicationChannel)
3421 return
3422 }
3423 }
3424}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003425
3426// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3427// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003428func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003429 if dh.getDeviceDeletionInProgressFlag() {
3430 // The device itself is going to be reset as part of deletion. So nothing to be done.
3431 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3432 return nil
3433 }
3434
Girish Gowdra491a9c62021-01-06 16:43:07 -08003435 // Step1 : Fill McastFlowOrGroupControlBlock
3436 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3437 // Step3 : Wait on response channel for response
3438 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003439 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003440 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3441 errChan := make(chan error)
3442 var groupID uint32
3443 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3444 ctx: ctx,
3445 flowOrGroupAction: action,
3446 flow: flow,
3447 group: group,
3448 errChan: &errChan,
3449 }
3450 if flow != nil {
3451 groupID = flow_utils.GetGroup(flow)
3452 } else if group != nil {
3453 groupID = group.Desc.GroupId
3454 } else {
3455 return errors.New("flow-and-group-both-nil")
3456 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003457 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3458 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3459 // Derive the appropriate go routine to handle the request by a simple module operation.
3460 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3461 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3462 // Wait for handler to return error value
3463 err := <-errChan
3464 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3465 return err
3466 }
3467 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3468 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003469}
3470
3471// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003472func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003473 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003474 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003475 // block on the channel to receive an incoming mcast flow/group
3476 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003477 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3478 if mcastFlowOrGroupCb.flow != nil {
3479 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3480 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3481 log.Fields{"device-id": dh.device.Id,
3482 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003483 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3484 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3485 for _, flMgr := range dh.flowMgr {
3486 if flMgr != nil {
3487 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3488 break
3489 }
3490 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003491 // Pass the return value over the return channel
3492 *mcastFlowOrGroupCb.errChan <- err
3493 } else { // flow remove
3494 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3495 log.Fields{"device-id": dh.device.Id,
3496 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003497 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3498 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3499 for _, flMgr := range dh.flowMgr {
3500 if flMgr != nil {
3501 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3502 break
3503 }
3504 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003505 // Pass the return value over the return channel
3506 *mcastFlowOrGroupCb.errChan <- err
3507 }
3508 } else { // mcast group
3509 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3510 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3511 log.Fields{"device-id": dh.device.Id,
3512 "groupToAdd": mcastFlowOrGroupCb.group})
3513 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3514 // Pass the return value over the return channel
3515 *mcastFlowOrGroupCb.errChan <- err
3516 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3517 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3518 log.Fields{"device-id": dh.device.Id,
3519 "groupToModify": mcastFlowOrGroupCb.group})
3520 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3521 // Pass the return value over the return channel
3522 *mcastFlowOrGroupCb.errChan <- err
3523 } else { // group remove
3524 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3525 log.Fields{"device-id": dh.device.Id,
3526 "groupToRemove": mcastFlowOrGroupCb.group})
3527 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3528 // Pass the return value over the return channel
3529 *mcastFlowOrGroupCb.errChan <- err
3530 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003531 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003532 case <-stopHandler:
3533 dh.mcastHandlerRoutineActive[routineIndex] = false
3534 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003535 }
3536 }
3537}
kesavand62126212021-01-12 04:56:06 -05003538
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003539// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003540func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003541 for i, v := range dh.stopMcastHandlerRoutine {
3542 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003543 select {
3544 case v <- true:
3545 case <-time.After(time.Second * 5):
3546 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3547 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003548 }
3549 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003550
3551 if dh.incomingMcastFlowOrGroup != nil {
3552 for k := range dh.incomingMcastFlowOrGroup {
3553 if dh.incomingMcastFlowOrGroup[k] != nil {
3554 dh.incomingMcastFlowOrGroup[k] = nil
3555 }
3556 }
3557 dh.incomingMcastFlowOrGroup = nil
3558 }
3559
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003560 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003561 logger.Debug(ctx, "stopped all mcast handler routines")
3562}
3563
Akash Kankanala041a2122024-10-16 15:49:22 +05303564// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003565func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003566 singleValResp := extension.SingleGetValueResponse{
3567 Response: &extension.GetValueResponse{
3568 Response: &extension.GetValueResponse_PortCoutners{
3569 PortCoutners: &extension.GetOltPortCountersResponse{},
3570 },
3571 },
3572 }
3573
Akash Kankanala041a2122024-10-16 15:49:22 +05303574 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003575 return &extension.SingleGetValueResponse{
3576 Response: &extension.GetValueResponse{
3577 Status: status,
3578 ErrReason: reason,
3579 },
3580 }
3581 }
3582
3583 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3584 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303585 // send error response
kesavand62126212021-01-12 04:56:06 -05003586 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3587 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3588 }
3589 statIndChn := make(chan bool, 1)
3590 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3591 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303592 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003593
3594 go func() {
3595 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3596 if err != nil {
3597 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3598 }
3599 }()
3600 select {
3601 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303602 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003603 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3604 case <-time.After(oltPortInfoTimeout * time.Second):
3605 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3606 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3607 case <-ctx.Done():
3608 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3609 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3610 }
3611 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
Akash Kankanala041a2122024-10-16 15:49:22 +05303612 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003613 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003614 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3615 cmnni := dh.portStats.collectNNIMetrics(intfID)
3616 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303617 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003618 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3619 }
3620 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3621 return &singleValResp
kesavand62126212021-01-12 04:56:06 -05003622 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3623 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003624 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003625 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3626 cmpon := dh.portStats.collectPONMetrics(intfID)
3627 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303628 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003629 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3630 }
3631 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3632 return &singleValResp
3633 }
3634 }
3635 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3636}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303637
Akash Kankanala041a2122024-10-16 15:49:22 +05303638//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303639func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303640 singleValResp := extension.SingleGetValueResponse{
3641 Response: &extension.GetValueResponse{
3642 Status: extension.GetValueResponse_OK,
3643 Response: &extension.GetValueResponse_OffloadedAppsStats{
3644 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3645 },
3646 },
3647 }
3648
3649 return &singleValResp
3650}
3651
Akash Kankanala041a2122024-10-16 15:49:22 +05303652//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303653func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303654 singleValResp := extension.SingleSetValueResponse{
3655 Response: &extension.SetValueResponse{
3656 Status: extension.SetValueResponse_OK,
3657 },
3658 }
3659
3660 return &singleValResp
3661}
3662
Akash Kankanala041a2122024-10-16 15:49:22 +05303663//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303664func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303665 singleValResp := extension.SingleSetValueResponse{
3666 Response: &extension.SetValueResponse{
3667 Status: extension.SetValueResponse_OK,
3668 },
3669 }
3670
3671 return &singleValResp
3672}
3673
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303674func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303675 singleValResp := extension.SingleGetValueResponse{
3676 Response: &extension.GetValueResponse{
3677 Response: &extension.GetValueResponse_OnuPonCounters{
3678 OnuPonCounters: &extension.GetOnuCountersResponse{},
3679 },
3680 },
3681 }
3682
Akash Kankanala041a2122024-10-16 15:49:22 +05303683 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303684 return &extension.SingleGetValueResponse{
3685 Response: &extension.GetValueResponse{
3686 Status: status,
3687 ErrReason: reason,
3688 },
3689 }
3690 }
3691 intfID := onuPonInfo.IntfId
3692 onuID := onuPonInfo.OnuId
3693 onuKey := dh.formOnuKey(intfID, onuID)
3694
3695 if _, ok := dh.onus.Load(onuKey); !ok {
3696 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3697 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3698 }
3699 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3700 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3701 if cmnni == nil {
3702 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3703 }
3704 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3705 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303706}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003707
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303708func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3709 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3710 if err != nil {
3711 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3712 return nil, err
3713 }
3714 if onuGemInfo != nil {
3715 if len(onuGemInfo.UniPorts) == 0 {
3716 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3717 return nil, err
3718 }
3719 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3720 return onuGemInfo, nil
3721 }
3722 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3723 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3724}
3725
3726func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3727 var err error
3728 var allocStats *oop.OnuAllocIdStatistics
3729 var onuGemStats *oop.GemPortStatistics
3730 for _, uni := range onuGemInfo.UniPorts {
3731 uniID := plt.UniIDFromPortNum(uni)
3732 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3733 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3734 if len(tpIDs) == 0 {
3735 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3736 continue
3737 }
3738 for _, tpId := range tpIDs {
3739 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3740 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3741 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3742 if techProfileInstance != nil {
3743 switch tpInst := techProfileInstance.(type) {
3744 case *tp_pb.TechProfileInstance:
3745 allocId := tpInst.UsScheduler.AllocId
3746 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3747 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3748 if err != nil {
3749 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3750 return err
3751 }
3752 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3753 allocIdInfo.AllocId = allocStats.AllocId
3754 allocIdInfo.RxBytes = allocStats.RxBytes
3755
3756 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3757
3758 gemPorts := tpInst.UpstreamGemPortAttributeList
3759 for _, gem := range gemPorts {
3760 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3761 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
3762 if err != nil {
3763 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
3764 return err
3765 }
3766 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
3767 gemStatsInfo.GemId = onuGemStats.GemportId
3768 gemStatsInfo.RxBytes = onuGemStats.RxBytes
3769 gemStatsInfo.RxPackets = onuGemStats.RxPackets
3770 gemStatsInfo.TxBytes = onuGemStats.TxBytes
3771 gemStatsInfo.TxPackets = onuGemStats.TxPackets
3772
3773 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
3774 }
3775 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
3776
3777 default:
3778 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
3779 return err
3780 }
3781 } else {
3782 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
3783 continue
3784 }
3785 }
3786 }
3787 return err
3788}
3789
3790//nolint:unparam
3791func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
3792 singleValResp := extension.SingleGetValueResponse{
3793 Response: &extension.GetValueResponse{
3794 Status: extension.GetValueResponse_OK,
3795 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
3796 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
3797 },
3798 },
3799 }
3800 errResp := func(status extension.GetValueResponse_Status,
3801 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3802 return &extension.SingleGetValueResponse{
3803 Response: &extension.GetValueResponse{
3804 Status: status,
3805 ErrReason: reason,
3806 },
3807 }
3808 }
3809
3810 var intfID, onuID uint32
3811 if onuDevice != nil {
3812 onuID = onuDevice.ProxyAddress.OnuId
3813 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
3814 }
3815
3816 onuKey := dh.formOnuKey(intfID, onuID)
3817 if _, ok := dh.onus.Load(onuKey); !ok {
3818 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
3819 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3820 }
3821 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
3822
3823 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
3824 if err == nil {
3825 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
3826 if err != nil {
3827 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3828 }
3829 } else {
3830 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3831 }
3832 return &singleValResp
3833}
3834
nikesh.krishnanc8473432023-06-14 12:14:54 +05303835func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303836 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3837 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3838 if err != nil {
3839 return nil, err
3840 }
3841 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303842}
3843
3844func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303845 Intf := oop.Interface{IntfId: intfID}
3846 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3847 if err != nil {
3848 return nil, err
3849 }
3850 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303851}
3852
Gamze Abaka85e9a142021-05-26 13:41:39 +00003853func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00003854 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3855 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3856 if err != nil {
3857 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3858 return generateSingleGetValueErrorResponse(err)
3859 }
3860 return &extension.SingleGetValueResponse{
3861 Response: &extension.GetValueResponse{
3862 Status: extension.GetValueResponse_OK,
3863 Response: &extension.GetValueResponse_RxPower{
3864 RxPower: &extension.GetRxPowerResponse{
3865 IntfId: rxPowerRequest.IntfId,
3866 OnuId: rxPowerRequest.OnuId,
3867 Status: rxPower.Status,
3868 FailReason: rxPower.FailReason.String(),
3869 RxPower: rxPower.RxPowerMeanDbm,
3870 },
3871 },
3872 },
3873 }
3874}
3875
praneeth nalmas55616d62023-02-06 09:19:18 +05303876func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05303877 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05303878 return &extension.SingleGetValueResponse{
3879 Response: &extension.GetValueResponse{
3880 Status: status,
3881 ErrReason: reason,
3882 },
3883 }
3884 }
3885
3886 resp := extension.SingleGetValueResponse{
3887 Response: &extension.GetValueResponse{
3888 Status: extension.GetValueResponse_OK,
3889 Response: &extension.GetValueResponse_OltRxPower{
3890 OltRxPower: &extension.GetOltRxPowerResponse{},
3891 },
3892 },
3893 }
3894
3895 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3896 portLabel := OltRxPowerRequest.PortLabel
3897 serialNumber := OltRxPowerRequest.OnuSn
3898
3899 portInfo := strings.Split(portLabel, "-")
3900 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3901
3902 if err != nil {
3903 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3904 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3905 }
3906
3907 if portInfo[0] != "pon" {
3908 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3909 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3910 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303911
3912 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05303913 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3914 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303915 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3916 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3917 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303918 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3919 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05303920 }
3921
3922 rxPowerValue := extension.RxPower{}
3923 rxPowerValue.OnuSn = onuDev.serialNumber
3924 rxPowerValue.Status = rxPower.GetStatus()
3925 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3926 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3927
3928 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05303929 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303930 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3931 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3932 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303933 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303934 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303935 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303936 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303937 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3938 if err != nil {
3939 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3940 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303941 rxPowerValue := extension.RxPower{}
3942 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3943 rxPowerValue.Status = rxPower.GetStatus()
3944 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3945 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3946
3947 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3948 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303949 }
3950 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3951 return true
3952 })
3953 }
3954 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3955 return &resp
3956}
3957
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05303958func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
3959 errResp := func(status extension.GetValueResponse_Status,
3960 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3961 return &extension.SingleGetValueResponse{
3962 Response: &extension.GetValueResponse{
3963 Status: status,
3964 ErrReason: reason,
3965 },
3966 }
3967 }
3968
3969 resp := extension.SingleGetValueResponse{
3970 Response: &extension.GetValueResponse{
3971 Status: extension.GetValueResponse_OK,
3972 Response: &extension.GetValueResponse_OltPonStatsResponse{
3973 OltPonStatsResponse: &extension.GetPonStatsResponse{},
3974 },
3975 },
3976 }
3977
3978 portLabel := ponStatsRequest.GetPortLabel()
3979 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
3980
3981 portInfo := strings.Split(portLabel, "-")
3982 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3983
3984 if err != nil {
3985 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3986 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3987 }
3988
3989 if portInfo[0] != "pon" {
3990 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
3991 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3992 }
3993
3994 Interface := oop.Interface{IntfId: uint32(portNumber)}
3995 ponStats, err := dh.Client.GetPonPortStatistics(ctx, &Interface)
3996 if err != nil {
3997 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
3998 return generateSingleGetValueErrorResponse(err)
3999 }
4000
4001 ponPortStats := resp.Response.GetOltPonStatsResponse()
4002 ponPortStats.PonPort = uint32(portNumber)
4003 ponPortStats.PortStatistics = ponStats
4004
4005 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
4006 return &resp
4007}
4008
4009func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
4010 errResp := func(status extension.GetValueResponse_Status,
4011 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
4012 return &extension.SingleGetValueResponse{
4013 Response: &extension.GetValueResponse{
4014 Status: status,
4015 ErrReason: reason,
4016 },
4017 }
4018 }
4019
4020 resp := extension.SingleGetValueResponse{
4021 Response: &extension.GetValueResponse{
4022 Status: extension.GetValueResponse_OK,
4023 Response: &extension.GetValueResponse_OltNniStatsResponse{
4024 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4025 },
4026 },
4027 }
4028
4029 portLabel := nniStatsRequest.GetPortLabel()
4030 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4031
4032 portInfo := strings.Split(portLabel, "-")
4033 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4034
4035 if err != nil {
4036 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4037 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4038 }
4039
4040 if portInfo[0] != "nni" {
4041 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4042 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4043 }
4044
4045 Interface := oop.Interface{IntfId: uint32(portNumber)}
4046 nniStats, err := dh.Client.GetNniPortStatistics(ctx, &Interface)
4047 if err != nil {
4048 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4049 return generateSingleGetValueErrorResponse(err)
4050 }
4051
4052 nniPortStats := resp.Response.GetOltNniStatsResponse()
4053 nniPortStats.NniPort = uint32(portNumber)
4054 nniPortStats.PortStatistics = nniStats
4055
4056 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4057 return &resp
4058}
4059
Akash Kankanala041a2122024-10-16 15:49:22 +05304060// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004061func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304062 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004063 return &extension.SingleGetValueResponse{
4064 Response: &extension.GetValueResponse{
4065 Status: status,
4066 ErrReason: reason,
4067 },
4068 }
4069 }
4070
4071 if err != nil {
4072 if e, ok := status.FromError(err); ok {
4073 switch e.Code() {
4074 case codes.Internal:
4075 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4076 case codes.DeadlineExceeded:
4077 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4078 case codes.Unimplemented:
4079 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4080 case codes.NotFound:
4081 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4082 }
4083 }
4084 }
4085
4086 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4087}
khenaidoo106c61a2021-08-11 18:05:46 -04004088
4089/*
4090Helper functions to communicate with Core
4091*/
4092
4093func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4094 cClient, err := dh.coreClient.GetCoreServiceClient()
4095 if err != nil || cClient == nil {
4096 return nil, err
4097 }
4098 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4099 defer cancel()
4100 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4101}
4102
khenaidoodc2116e2021-10-19 17:33:19 -04004103func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004104 cClient, err := dh.coreClient.GetCoreServiceClient()
4105 if err != nil || cClient == nil {
4106 return nil, err
4107 }
4108 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4109 defer cancel()
4110 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4111}
4112
khenaidoodc2116e2021-10-19 17:33:19 -04004113func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004114 cClient, err := dh.coreClient.GetCoreServiceClient()
4115 if err != nil || cClient == nil {
4116 return err
4117 }
4118 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4119 defer cancel()
4120 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4121 return err
4122}
4123
4124func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4125 cClient, err := dh.coreClient.GetCoreServiceClient()
4126 if err != nil || cClient == nil {
4127 return nil, err
4128 }
4129 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4130 defer cancel()
4131 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4132}
4133
4134func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4135 cClient, err := dh.coreClient.GetCoreServiceClient()
4136 if err != nil || cClient == nil {
4137 return nil, err
4138 }
4139 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4140 defer cancel()
4141 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4142}
4143
4144func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4145 cClient, err := dh.coreClient.GetCoreServiceClient()
4146 if err != nil || cClient == nil {
4147 return err
4148 }
4149 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4150 defer cancel()
4151 _, err = cClient.DeviceUpdate(subCtx, device)
4152 return err
4153}
4154
khenaidoodc2116e2021-10-19 17:33:19 -04004155func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004156 cClient, err := dh.coreClient.GetCoreServiceClient()
4157 if err != nil || cClient == nil {
4158 return nil, err
4159 }
4160 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4161 defer cancel()
4162 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4163}
4164
khenaidoodc2116e2021-10-19 17:33:19 -04004165func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004166 cClient, err := dh.coreClient.GetCoreServiceClient()
4167 if err != nil || cClient == nil {
4168 return err
4169 }
4170 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4171 defer cancel()
4172 _, err = cClient.SendPacketIn(subCtx, pkt)
4173 return err
4174}
4175
4176func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4177 cClient, err := dh.coreClient.GetCoreServiceClient()
4178 if err != nil || cClient == nil {
4179 return err
4180 }
4181 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4182 defer cancel()
4183 _, err = cClient.PortCreated(subCtx, port)
4184 return err
4185}
4186
khenaidoodc2116e2021-10-19 17:33:19 -04004187func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004188 cClient, err := dh.coreClient.GetCoreServiceClient()
4189 if err != nil || cClient == nil {
4190 return err
4191 }
4192 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4193 defer cancel()
4194 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4195 return err
4196}
4197
khenaidoodc2116e2021-10-19 17:33:19 -04004198func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004199 cClient, err := dh.coreClient.GetCoreServiceClient()
4200 if err != nil || cClient == nil {
4201 return err
4202 }
4203 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4204 defer cancel()
4205 _, err = cClient.PortStateUpdate(subCtx, portState)
4206 return err
4207}
4208
khenaidoodc2116e2021-10-19 17:33:19 -04004209func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004210 cClient, err := dh.coreClient.GetCoreServiceClient()
4211 if err != nil || cClient == nil {
4212 return nil, err
4213 }
4214 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4215 defer cancel()
4216 return cClient.GetDevicePort(subCtx, portFilter)
4217}
4218
nikesh.krishnanc8473432023-06-14 12:14:54 +05304219func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4220 cClient, err := dh.coreClient.GetCoreServiceClient()
4221 if err != nil || cClient == nil {
4222 return nil, err
4223 }
4224 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4225 defer cancel()
4226 return cClient.GetPorts(subCtx, portFilter)
4227}
4228
khenaidoo106c61a2021-08-11 18:05:46 -04004229/*
4230Helper functions to communicate with child adapter
4231*/
4232
khenaidoodc2116e2021-10-19 17:33:19 -04004233func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004234 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4235 if err != nil || aClient == nil {
4236 return err
4237 }
4238 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4239 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4240 defer cancel()
4241 _, err = aClient.OmciIndication(subCtx, response)
4242 return err
4243}
4244
khenaidoodc2116e2021-10-19 17:33:19 -04004245func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004246 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4247 if err != nil || aClient == nil {
4248 return err
4249 }
4250 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4251 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4252 defer cancel()
4253 _, err = aClient.OnuIndication(subCtx, onuInd)
4254 return err
4255}
4256
khenaidoodc2116e2021-10-19 17:33:19 -04004257func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004258 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4259 if err != nil || aClient == nil {
4260 return err
4261 }
4262 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4263 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4264 defer cancel()
4265 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4266 return err
4267}
4268
khenaidoodc2116e2021-10-19 17:33:19 -04004269func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004270 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4271 if err != nil || aClient == nil {
4272 return err
4273 }
4274 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4275 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4276 defer cancel()
4277 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4278 return err
4279}
4280
khenaidoodc2116e2021-10-19 17:33:19 -04004281func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004282 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4283 if err != nil || aClient == nil {
4284 return err
4285 }
4286 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4287 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4288 defer cancel()
4289 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4290 return err
4291}
4292
4293/*
4294Helper functions for remote communication
4295*/
4296
4297// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4298// supports is deleted
4299func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4300 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4301
4302 dh.lockChildAdapterClients.Lock()
4303 defer dh.lockChildAdapterClients.Unlock()
4304 if _, ok := dh.childAdapterClients[endpoint]; ok {
4305 // Already set
4306 return nil
4307 }
4308
4309 // Setup child's adapter grpc connection
4310 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004311 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4312 dh.cfg.AdapterEndpoint,
4313 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004314 "onu_inter_adapter_service.OnuInterAdapterService",
4315 dh.onuInterAdapterRestarted,
4316 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004317 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4318 return err
4319 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304320 retryCodes := []codes.Code{
4321 codes.Unavailable, // server is currently unavailable
4322 codes.DeadlineExceeded, // deadline for the operation was exceeded
4323 }
4324 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4325 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 -04004326
nikesh.krishnand9812542023-08-01 18:31:39 +05304327 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004328 // Wait until we have a connection to the child adapter.
4329 // Unlimited retries or until context expires
4330 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4331 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4332 for {
4333 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4334 if err == nil && client != nil {
4335 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4336 break
4337 }
4338 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4339 // Backoff
4340 if err = backoff.Backoff(subCtx); err != nil {
4341 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4342 break
4343 }
4344 }
4345 return nil
4346}
4347
khenaidoodc2116e2021-10-19 17:33:19 -04004348func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004349 // First check from cache
4350 dh.lockChildAdapterClients.RLock()
4351 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4352 dh.lockChildAdapterClients.RUnlock()
4353 return cgClient.GetOnuInterAdapterServiceClient()
4354 }
4355 dh.lockChildAdapterClients.RUnlock()
4356
4357 // Set the child connection - can occur on restarts
4358 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4359 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4360 cancel()
4361 if err != nil {
4362 return nil, err
4363 }
4364
4365 // Get the child client now
4366 dh.lockChildAdapterClients.RLock()
4367 defer dh.lockChildAdapterClients.RUnlock()
4368 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4369 return cgClient.GetOnuInterAdapterServiceClient()
4370 }
4371 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4372}
4373
4374func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4375 dh.lockChildAdapterClients.Lock()
4376 defer dh.lockChildAdapterClients.Unlock()
4377 for key, client := range dh.childAdapterClients {
4378 client.Stop(ctx)
4379 delete(dh.childAdapterClients, key)
4380 }
4381}
4382
khenaidooefff76e2021-12-15 16:51:30 -05004383// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4384func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4385 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004386 return nil
4387}
4388
khenaidooefff76e2021-12-15 16:51:30 -05004389// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4390func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4391 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004392 return nil
4393 }
khenaidooefff76e2021-12-15 16:51:30 -05004394 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004395}
Girish Gowdra950326e2021-11-05 12:43:24 -07004396
4397func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4398 dh.lockDevice.Lock()
4399 defer dh.lockDevice.Unlock()
4400 dh.isDeviceDeletionInProgress = flag
4401}
4402
4403func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4404 dh.lockDevice.RLock()
4405 defer dh.lockDevice.RUnlock()
4406 return dh.isDeviceDeletionInProgress
4407}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004408
4409// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4410// Returns false if waiting timed out.
4411func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4412 c := make(chan struct{})
4413 go func() {
4414 defer close(c)
4415 wg.Wait()
4416 }()
4417 select {
4418 case <-c:
4419 return true // completed normally
4420 case <-time.After(timeout):
4421 return false // timed out
4422 }
4423}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304424
4425func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4426 val, err := json.Marshal(signature)
4427 if err != nil {
4428 logger.Error(ctx, "failed-to-marshal")
4429 return
4430 }
4431 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4432 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4433 }
4434}
4435
4436func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4437 var signature uint32
4438
4439 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4440 if er == nil {
4441 if Value != nil {
4442 Val, er := kvstore.ToByte(Value.Value)
4443 if er != nil {
4444 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4445 return signature
4446 }
4447 if er = json.Unmarshal(Val, &signature); er != nil {
4448 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4449 return signature
4450 }
4451 }
4452 }
4453 return signature
4454}